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