@@ -376,7 +376,9 @@ -(instancetype)initWithGLProgram:(GLuint)program uniformSetters:(NSDictionary *)
376
376
{
377
377
NSUInteger vertexIndex = vertexArg.index ;
378
378
NSUInteger fragmentIndex = fragmentArg.index ;
379
- size_t bytes = vertexArg.bufferDataSize ;
379
+
380
+ // vertexArg may be nil.
381
+ size_t bytes = (vertexArg.bufferDataSize ?: fragmentArg.bufferDataSize );
380
382
381
383
CCMetalContext *context = [CCMetalContext currentContext ];
382
384
@@ -393,20 +395,27 @@ -(instancetype)initWithGLProgram:(GLuint)program uniformSetters:(NSDictionary *)
393
395
};
394
396
} else {
395
397
// If both args are active, they must match.
396
- NSCAssert (!vertexArg || !fragmentArg || bytes == fragmentArg.bufferDataSize, @" Vertex and fragment argument type don't match for '%@ '." , vertexArg.name);
398
+ NSCAssert (!vertexArg || !fragmentArg || vertexArg.bufferDataSize == fragmentArg.bufferDataSize, @" Vertex and fragment argument type don't match for '%@ '." , vertexArg.name);
397
399
398
400
return ^(CCRenderer *renderer, NSDictionary *shaderUniforms, NSDictionary *globalShaderUniforms){
399
401
CCGraphicsBufferMetal *uniformBuffer = (CCGraphicsBufferMetal *)renderer->_buffers ->_uniformBuffer ;
400
402
id <MTLBuffer > metalBuffer = uniformBuffer->_buffer ;
401
403
402
- NSNumber *globalOffset = renderer->_globalShaderUniformBufferOffsets [name];
403
- NSUInteger offset = globalOffset.unsignedIntegerValue ;
404
+ NSUInteger offset = 0 ;
404
405
405
- if (!globalOffset){
406
+ NSValue *value = shaderUniforms[name];
407
+ if (value){
408
+ // Try finding a per-node value first and append it to the uniform buffer.
406
409
void *buff = CCGraphicsBufferPushElements (uniformBuffer, bytes);
407
- [shaderUniforms[name] getValue: buff];
410
+ [value getValue: buff];
408
411
409
412
offset = buff - uniformBuffer->_ptr ;
413
+ } else {
414
+ // Look for a global offset instead.
415
+ NSNumber *globalOffset = renderer->_globalShaderUniformBufferOffsets [name];
416
+ NSCAssert (globalOffset, @" Shader value named '%@ ' not found." , name);
417
+
418
+ offset = globalOffset.unsignedIntegerValue ;
410
419
}
411
420
412
421
id <MTLRenderCommandEncoder > renderEncoder = context->_currentRenderCommandEncoder ;
@@ -509,6 +518,8 @@ -(instancetype)initWithGLProgram:(GLuint)program uniformSetters:(NSDictionary *)
509
518
-(instancetype )initWithMetalVertexFunction : (id <MTLFunction >)vertexFunction fragmentFunction : (id <MTLFunction >)fragmentFunction
510
519
{
511
520
if ((self = [super init ])){
521
+ NSAssert (vertexFunction && fragmentFunction, @" Must create have both a vertex and fragment function to make a CCShader." );
522
+
512
523
_vertexFunction = vertexFunction;
513
524
_fragmentFunction = fragmentFunction;
514
525
@@ -517,13 +528,73 @@ -(instancetype)initWithMetalVertexFunction:(id<MTLFunction>)vertexFunction fragm
517
528
518
529
return self;
519
530
}
520
- #endif
521
531
522
- -(instancetype )initWithVertexShaderSource : (NSString *)vertexSource fragmentShaderSource : (NSString *)fragmentSource
532
+ -(instancetype )initWithMetalVertexShaderSource : (NSString *)vertexSource fragmentShaderSource : (NSString *)fragmentSource
523
533
{
524
- #warning TODO
525
- if ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIMetal) return self;
534
+ CCMetalContext *context = [CCMetalContext currentContext ];
535
+ NSString *header = CC_METAL (
536
+ using namespace metal;
537
+
538
+ typedef struct CCVertex {
539
+ float4 position;
540
+ float2 texCoord1;
541
+ float2 texCoord2;
542
+ float4 color;
543
+ } CCVertex;
544
+
545
+ typedef struct CCFragData {
546
+ float4 position [[position]];
547
+ float2 texCoord1;
548
+ float2 texCoord2;
549
+ half4 color;
550
+ } CCFragData;
551
+
552
+ typedef struct CCGlobalUniforms {
553
+ float4x4 projection;
554
+ float4x4 projectionInv;
555
+ float2 viewSize;
556
+ float2 viewSizeInPixels;
557
+ float4 time;
558
+ float4 sinTime;
559
+ float4 cosTime;
560
+ float4 random01;
561
+ } CCGlobalUniforms;
562
+
563
+ );
564
+
565
+ id <MTLFunction > vertexFunction = nil ;
566
+ if (vertexSource == CCDefaultVShader){
567
+ // Use the default vertex shader.
568
+ vertexFunction = [context.library newFunctionWithName: @" CCVertexFunctionDefault" ];
569
+ } else {
570
+ // Append on the standard header since JIT compiled shaders can't use #import
571
+ vertexSource = [header stringByAppendingString: vertexSource];
572
+
573
+ // Compile the vertex shader.
574
+ NSError *verr = nil ;
575
+ id <MTLLibrary > vlib = [context.device newLibraryWithSource: vertexSource options: nil error: &verr];
576
+ if (verr) CCLOG (@" Error compiling metal vertex shader: %@ " , verr);
577
+
578
+ vertexFunction = [vlib newFunctionWithName: @" ShaderMain" ];
579
+ }
580
+
581
+ // Append on the standard header since JIT compiled shaders can't use #import
582
+ fragmentSource = [header stringByAppendingString: fragmentSource];
526
583
584
+ // compile the fragment shader.
585
+ NSError *ferr = nil ;
586
+ id <MTLLibrary > flib = [context.device newLibraryWithSource: fragmentSource options: nil error: &ferr];
587
+ if (ferr) CCLOG (@" Error compiling metal fragment shader: %@ " , ferr);
588
+
589
+ id <MTLFunction > fragmentFunction = [flib newFunctionWithName: @" ShaderMain" ];
590
+
591
+ // Done!
592
+ return [self initWithMetalVertexFunction: vertexFunction fragmentFunction: fragmentFunction];
593
+ }
594
+ #endif
595
+
596
+ -(instancetype )initWithGLVertexShaderSource : (NSString *)vertexSource fragmentShaderSource : (NSString *)fragmentSource
597
+ {
527
598
__block typeof (self) blockself = self;
528
599
529
600
CCRenderDispatch (NO , ^{
@@ -555,6 +626,18 @@ -(instancetype)initWithVertexShaderSource:(NSString *)vertexSource fragmentShade
555
626
return blockself;
556
627
}
557
628
629
+ -(instancetype )initWithVertexShaderSource : (NSString *)vertexSource fragmentShaderSource : (NSString *)fragmentSource
630
+ {
631
+ #if __CC_METAL_SUPPORTED_AND_ENABLED
632
+ if ([CCConfiguration sharedConfiguration ].graphicsAPI == CCGraphicsAPIMetal){
633
+ return [self initWithMetalVertexShaderSource: vertexSource fragmentShaderSource: fragmentSource];
634
+ }
635
+ #endif
636
+ {
637
+ return [self initWithGLVertexShaderSource: vertexSource fragmentShaderSource: fragmentSource];
638
+ }
639
+ }
640
+
558
641
-(instancetype )initWithFragmentShaderSource : (NSString *)source
559
642
{
560
643
return [self initWithVertexShaderSource: CCDefaultVShader fragmentShaderSource: source];
0 commit comments