-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCNC_Renderer.mm
More file actions
186 lines (144 loc) · 6.7 KB
/
Copy pathCNC_Renderer.mm
File metadata and controls
186 lines (144 loc) · 6.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include <Metal/Metal.h>
#include <MetalKit/MetalKit.h>
#include "CNC_Types.h"
#include <imgui.h>
void checkError( NSError* error )
{
if( error != NULL )
{
NSLog( @"%@", [error localizedDescription] );
}
}
@interface MetalRenderer : NSObject< MTKViewDelegate >
{
@public
MTKView* m_view;
id<MTLDevice> m_device;
id<MTLCommandQueue> m_queue;
id<MTLRenderPipelineState> m_pipelineState;
struct UniformData m_uniform;
id<MTLBuffer> m_vertexBuffer;
id<MTLBuffer> m_indexBuffer;
id<MTLBuffer> m_uniformBuffer;
u32 m_numVertices;
u32 m_numIndices;
}
- (void)setup;
- (void)loadShaders;
@end
@implementation MetalRenderer
- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
{
m_uniform.m_screenSize.x = size.width;
m_uniform.m_screenSize.y = size.height;
}
- (void)drawInMTKView:(nonnull MTKView *)view
{
@autoreleasepool
{
id<MTLCommandBuffer> commandBuffer = [m_queue commandBuffer];
id<MTLRenderCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor: [m_view currentRenderPassDescriptor]];
[commandEncoder setRenderPipelineState: m_pipelineState];
[commandEncoder setVertexBuffer: m_vertexBuffer offset: 0 atIndex: 0]; // vertices
[commandEncoder setVertexBuffer: m_uniformBuffer offset:0 atIndex: 1]; // uniforms (projection)
[commandEncoder drawIndexedPrimitives: MTLPrimitiveTypeTriangle
indexCount: m_numIndices
indexType: MTLIndexTypeUInt32
indexBuffer: m_indexBuffer
indexBufferOffset: 0
instanceCount:1];
// render the draw calls
// render the ui on top of the scene
ImGui::Render();
ImGui_ImplMetal_RenderDrawData( ImGui::GetDrawData(), commandBuffer, commandEncoder);
[commandEncoder endEncoding];
[commandBuffer presentDrawable: [m_view currentDrawable]];
[commandBuffer commit];
}
}
- (void)setup
{
@autoreleasepool
{
[self loadShaders];
m_vertexBuffer = [m_device newBufferWithLength: sizeof( struct VertexInput ) * 8 options: MTLResourceCPUCacheModeDefaultCache];
m_uniformBuffer = [m_device newBufferWithLength: sizeof( struct UniformData ) options: MTLResourceCPUCacheModeDefaultCache];
m_indexBuffer = [m_device newBufferWithLength: sizeof( u32 ) * 30 options: MTLResourceCPUCacheModeDefaultCache];
m_uniform.m_screenSize.x = m_view.frame.size.width;
m_uniform.m_screenSize.y = m_view.frame.size.height;
}
}
- (void)loadShaders
{
@autoreleasepool
{
NSError* error = NULL;
NSString* shaderSource = [NSString stringWithContentsOfFile: @"CNC_Shader.metal" encoding: NSUTF8StringEncoding error: &error];
checkError( error );
MTLCompileOptions* options = [MTLCompileOptions new];
id<MTLLibrary> library = [m_device newLibraryWithSource: shaderSource options: options error: &error];
checkError( error );
id<MTLFunction> vertexShader = [library newFunctionWithName:@"VertexShader"];
id<MTLFunction> fragmentShader = [library newFunctionWithName:@"FragmentShader"];
if( vertexShader == NULL ) NSLog( @"could not load vertex shader" );
if( fragmentShader == NULL ) NSLog( @"could not load fragment shader " );
MTLVertexDescriptor* vertexDesc = [MTLVertexDescriptor new];
vertexDesc.attributes[0].bufferIndex = 0;
vertexDesc.attributes[0].format = MTLVertexFormatFloat3;
vertexDesc.attributes[0].offset = offsetof( struct VertexInput, m_position );
vertexDesc.attributes[1].bufferIndex = 0;
vertexDesc.attributes[1].format = MTLVertexFormatFloat2;
vertexDesc.attributes[1].offset = offsetof( struct VertexInput, m_uv );
vertexDesc.layouts[0].stride = sizeof( struct VertexInput );
vertexDesc.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
MTLRenderPipelineDescriptor* renderDesc = [MTLRenderPipelineDescriptor new];
renderDesc.vertexFunction = vertexShader;
renderDesc.fragmentFunction = fragmentShader;
renderDesc.vertexDescriptor = vertexDesc;
renderDesc.colorAttachments[0].pixelFormat = [m_view colorPixelFormat];
m_pipelineState = [m_device newRenderPipelineStateWithDescriptor: renderDesc error: &error];
checkError( error );
}
}
@end
MetalRenderer* CreateMetalRenderer()
{
MetalRenderer* renderer = [MetalRenderer new];
CGRect contentRect = CGRectMake( 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT );
renderer->m_device = MTLCreateSystemDefaultDevice();
renderer->m_view = [[MTKView alloc] initWithFrame: contentRect device: renderer->m_device];
[renderer->m_view setDelegate: renderer];
[renderer->m_view setPaused: true];
[renderer->m_view setNeedsDisplay: false];
[renderer->m_view setClearColor: MTLClearColorMake( 1.0, 0.0, 0.0, 1.0) ];
renderer->m_queue = [renderer->m_device newCommandQueue];
[renderer setup];
return renderer;
}
void Render( MetalRenderer* renderer )
{
[renderer->m_view draw];
}
void SubmitDrawCall( void* renderer, DrawCall* call )
{
MetalRenderer* metalRenderer = (MetalRenderer*)renderer;
memcpy( [metalRenderer->m_vertexBuffer contents], call->m_vertices, call->m_numVertices * sizeof( struct VertexInput ) );
memcpy( [metalRenderer->m_indexBuffer contents], call->m_indices, call->m_numIndices * sizeof( u32) );
metalRenderer->m_numVertices = call->m_numVertices;
metalRenderer->m_numIndices = call->m_numIndices;
}
void SetCameraData( void* renderer, m4 projectionMatrix, m4 viewTransform, m4 scaleTransform, struct Quarternion rotation, struct Quarternion inverse )
{
MetalRenderer* metalRenderer = (MetalRenderer*)renderer;
metalRenderer->m_uniform.m_projectionMatrix = projectionMatrix;
metalRenderer->m_uniform.m_viewTransform = viewTransform;
metalRenderer->m_uniform.m_scaleTransform = scaleTransform;
metalRenderer->m_uniform.m_rotationQuarternion = rotation;
metalRenderer->m_uniform.m_inverseRotation = inverse;
memcpy( [metalRenderer->m_uniformBuffer contents], &metalRenderer->m_uniform, sizeof( struct UniformData ) );
}
void ReloadShaders( void* renderer )
{
MetalRenderer* metalRenderer = (MetalRenderer*)renderer;
[metalRenderer loadShaders];
}