|
1 #import "MTLPipelineStatesStorage.h" |
|
2 #import "Trace.h" |
|
3 |
|
4 #include "GraphicsPrimitiveMgr.h" |
|
5 #import "common.h" |
|
6 |
|
7 @implementation MTLPipelineStatesStorage |
|
8 |
|
9 @synthesize device; |
|
10 @synthesize library; |
|
11 @synthesize shaders; |
|
12 @synthesize states; |
|
13 @synthesize templateRenderPipelineDesc; |
|
14 @synthesize templateTexturePipelineDesc; |
|
15 |
|
16 - (id) initWithDevice:(id<MTLDevice>)dev shaderLibPath:(NSString *)shadersLib { |
|
17 self = [super init]; |
|
18 if (self == nil) return self; |
|
19 |
|
20 self.device = dev; |
|
21 |
|
22 NSError *error = nil; |
|
23 self.library = [dev newLibraryWithFile:shadersLib error:&error]; |
|
24 if (!self.library) { |
|
25 NSLog(@"Failed to load library. error %@", error); |
|
26 exit(0); |
|
27 } |
|
28 self.shaders = [NSMutableDictionary dictionaryWithCapacity:10]; |
|
29 self.states = [NSMutableDictionary dictionaryWithCapacity:10]; |
|
30 |
|
31 { // init template descriptors |
|
32 MTLVertexDescriptor *vertDesc = [[MTLVertexDescriptor new] autorelease]; |
|
33 vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat3; |
|
34 vertDesc.attributes[VertexAttributePosition].offset = 0; |
|
35 vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer; |
|
36 vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct Vertex); |
|
37 vertDesc.layouts[MeshVertexBuffer].stepRate = 1; |
|
38 vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex; |
|
39 |
|
40 self.templateRenderPipelineDesc = [[MTLRenderPipelineDescriptor new] autorelease]; |
|
41 self.templateRenderPipelineDesc.sampleCount = 1; |
|
42 self.templateRenderPipelineDesc.vertexDescriptor = vertDesc; |
|
43 self.templateRenderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; |
|
44 self.templateRenderPipelineDesc.label = @"template_render"; |
|
45 |
|
46 self.templateTexturePipelineDesc = [[self.templateRenderPipelineDesc copy] autorelease]; |
|
47 self.templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2; |
|
48 self.templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 3*sizeof(float); |
|
49 self.templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer; |
|
50 self.templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stride = sizeof(struct TxtVertex); |
|
51 self.templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepRate = 1; |
|
52 self.templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex; |
|
53 self.templateTexturePipelineDesc.label = @"template_texture"; |
|
54 } |
|
55 |
|
56 { // pre-create main states |
|
57 [self getRenderPipelineState:YES]; |
|
58 [self getRenderPipelineState:NO]; |
|
59 [self getTexturePipelineState:NO compositeRule:RULE_Src]; |
|
60 [self getTexturePipelineState:NO compositeRule:RULE_SrcOver]; |
|
61 } |
|
62 |
|
63 return self; |
|
64 } |
|
65 |
|
66 - (id<MTLRenderPipelineState>) getRenderPipelineState:(bool)isGradient { |
|
67 NSString * uid = [NSString stringWithFormat:@"render_grad[%d]", isGradient]; |
|
68 |
|
69 id<MTLRenderPipelineState> result = [self.states valueForKey:uid]; |
|
70 if (result == nil) { |
|
71 id<MTLFunction> vertexShader = isGradient ? [self getShader:@"vert_grad"] : [self getShader:@"vert_col"]; |
|
72 id<MTLFunction> fragmentShader = isGradient ? [self getShader:@"frag_grad"] : [self getShader:@"frag_col"]; |
|
73 MTLRenderPipelineDescriptor *pipelineDesc = [[self.templateRenderPipelineDesc copy] autorelease]; |
|
74 pipelineDesc.vertexFunction = vertexShader; |
|
75 pipelineDesc.fragmentFunction = fragmentShader; |
|
76 pipelineDesc.label = uid; |
|
77 |
|
78 NSError *error = nil; |
|
79 result = [self.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&error]; |
|
80 if (result == nil) { |
|
81 NSLog(@"Failed to create render pipeline state '%@', error %@", uid, error); |
|
82 exit(0); |
|
83 } |
|
84 |
|
85 [self.states setValue:result forKey:uid]; |
|
86 } |
|
87 |
|
88 return result; |
|
89 }; |
|
90 |
|
91 - (id<MTLRenderPipelineState>) getTexturePipelineState:(bool)isSourcePremultiplied compositeRule:(int)compositeRule { |
|
92 NSString * uid = [NSString stringWithFormat:@"texture_compositeRule[%d]", compositeRule]; |
|
93 |
|
94 id<MTLRenderPipelineState> result = [self.states valueForKey:uid]; |
|
95 if (result == nil) { |
|
96 id<MTLFunction> vertexShader = [self getShader:@"vert_txt"]; |
|
97 id<MTLFunction> fragmentShader = [self getShader:@"frag_txt"]; |
|
98 MTLRenderPipelineDescriptor *pipelineDesc = [[self.templateTexturePipelineDesc copy] autorelease]; |
|
99 pipelineDesc.vertexFunction = vertexShader; |
|
100 pipelineDesc.fragmentFunction = fragmentShader; |
|
101 |
|
102 if (compositeRule != RULE_Src) { |
|
103 pipelineDesc.colorAttachments[0].blendingEnabled = YES; |
|
104 |
|
105 if (!isSourcePremultiplied) |
|
106 pipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha; |
|
107 |
|
108 //RGB = Source.rgb * SBF + Dest.rgb * DBF |
|
109 //A = Source.a * SBF + Dest.a * DBF |
|
110 // |
|
111 //default SRC: |
|
112 //DBF=0 |
|
113 //SBF=1 |
|
114 if (compositeRule == RULE_SrcOver) { |
|
115 // SRC_OVER (Porter-Duff Source Over Destination rule): |
|
116 // Ar = As + Ad*(1-As) |
|
117 // Cr = Cs + Cd*(1-As) |
|
118 pipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; |
|
119 pipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; |
|
120 } else { |
|
121 J2dTrace1(J2D_TRACE_ERROR, "Unimplemented composite rule %d (will be used Src)", compositeRule); |
|
122 pipelineDesc.colorAttachments[0].blendingEnabled = NO; |
|
123 } |
|
124 } |
|
125 |
|
126 NSError *error = nil; |
|
127 result = [self.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&error]; |
|
128 if (result == nil) { |
|
129 NSLog(@"Failed to create texture pipeline state '%@', error %@", uid, error); |
|
130 exit(0); |
|
131 } |
|
132 |
|
133 [self.states setValue:result forKey:uid]; |
|
134 } |
|
135 |
|
136 return result; |
|
137 } |
|
138 |
|
139 - (id<MTLFunction>) getShader:(NSString *)name { |
|
140 id<MTLFunction> result = [self.shaders valueForKey:name]; |
|
141 if (result == nil) { |
|
142 result = [[self.library newFunctionWithName:name] autorelease]; |
|
143 [self.shaders setValue:result forKey:name]; |
|
144 } |
|
145 return result; |
|
146 } |
|
147 @end |