Skip to content

Commit e86030e

Browse files
committed
Global uniform buffers working.
1 parent 5113ebb commit e86030e

File tree

6 files changed

+81
-16
lines changed

6 files changed

+81
-16
lines changed

cocos2d/CCNoARC.m

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,6 @@ -(void)invokeOnRenderer:(CCRenderer *)renderer
285285

286286
#if __CC_METAL_SUPPORTED_AND_ENABLED
287287

288-
// This is effectively hardcoded to 10 by Apple's docs and there is no API to query capabilities...
289-
// Seems like an oversight, but whatever.
290-
#define CCMTL_MAX_TEXTURES 10
291-
292-
293288
@interface CCRenderStateMetal : CCRenderState @end
294289
@implementation CCRenderStateMetal {
295290
id<MTLRenderPipelineState> _renderPipelineState;
@@ -360,8 +355,8 @@ @implementation CCRenderStateMetal {
360355
CCTexture *mainTexture = self->_shaderUniforms[CCShaderUniformMainTexture];
361356

362357
self->_textureRange = NSMakeRange(0, 1);
363-
self->_samplers[0] = mainTexture.metalSampler;
364-
self->_textures[0] = mainTexture.metalTexture;
358+
self->_samplers[0] = [mainTexture.metalSampler retain];
359+
self->_textures[0] = [mainTexture.metalTexture retain];
365360

366361
self->_uniformsPrepared = YES;
367362
}
@@ -370,7 +365,7 @@ @implementation CCRenderStateMetal {
370365
static void
371366
CCRenderStateMetalTransition(CCRenderStateMetal *self, CCRenderer *renderer, CCRenderStateMetal *previous)
372367
{
373-
CCMetalContext *context = renderer->_context;
368+
CCMetalContext *context = renderer->_metalContext;
374369
id<MTLRenderCommandEncoder> renderEncoder = context->_currentRenderCommandEncoder;
375370
[renderEncoder setRenderPipelineState:self->_renderPipelineState];
376371

@@ -416,7 +411,7 @@ -(instancetype)initWithMode:(CCRenderCommandDrawMode)mode renderState:(CCRenderS
416411

417412
-(void)invokeOnRenderer:(CCRenderer *)renderer
418413
{
419-
CCMetalContext *context = renderer->_context;
414+
CCMetalContext *context = renderer->_metalContext;
420415
id<MTLRenderCommandEncoder> renderEncoder = context->_currentRenderCommandEncoder;
421416
id<MTLBuffer> indexBuffer = ((CCGraphicsBufferMetal *)renderer->_elementBuffer)->_buffer;
422417

cocos2d/CCRenderer.m

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,16 @@ -(instancetype)init
546546
_threadsafe = YES;
547547
_queue = [NSMutableArray array];
548548

549-
#warning TEMP
550-
// Should probably change the init method to pass this in?
551-
_context = [NSClassFromString(@"CCMetalContext") currentContext];
549+
#if __CC_METAL_SUPPORTED_AND_ENABLED
550+
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
551+
// TODO: This is sort of gross. Would like it to move somewhere else.
552+
_metalContext = (CCMetalContext *)[NSClassFromString(@"CCMetalContext") currentContext];
553+
554+
// Default to half a megabyte of initial uniform storage.
555+
NSUInteger uniformCapacity = 500*1024;
556+
_uniformBuffer = [[CCGraphicsBufferClass alloc] initWithCapacity:uniformCapacity elementSize:1 type:CCGraphicsBufferTypeUniform];
557+
}
558+
#endif
552559
}
553560

554561
return self;
@@ -649,23 +656,54 @@ -(void)flush
649656
{
650657
CCGL_DEBUG_PUSH_GROUP_MARKER("CCRenderer: Flush");
651658

659+
// Commit the geometry buffers to be used by the rendering commmands.
652660
CCGL_DEBUG_INSERT_EVENT_MARKER("Buffering");
653661
[_vertexBuffer commit];
654662
[_elementBuffer commit];
655663
CC_CHECK_GL_ERROR_DEBUG();
656664

665+
// The render commands build the uniform buffers. (only used by Metal currently)
666+
[_uniformBuffer prepare];
667+
668+
// TODO This should probably be moved eventually, but I'm not sure where.
669+
// Probably never going to support uniform buffers in GL and making CCRenderer abstract is ugh...
670+
#if __CC_METAL_SUPPORTED_AND_ENABLED
671+
if(_metalContext){
672+
CCGlobalUniforms globalUniforms = {};
673+
const NSUInteger globalUniformBytes = sizeof(globalUniforms);
674+
675+
[_globalShaderUniforms[CCShaderUniformProjection] getValue:&globalUniforms.projection];
676+
[_globalShaderUniforms[CCShaderUniformProjectionInv] getValue:&globalUniforms.projectionInv];
677+
[_globalShaderUniforms[CCShaderUniformViewSize] getValue:&globalUniforms.viewSize];
678+
[_globalShaderUniforms[CCShaderUniformViewSizeInPixels] getValue:&globalUniforms.viewSizeInPixels];
679+
[_globalShaderUniforms[CCShaderUniformTime] getValue:&globalUniforms.time];
680+
[_globalShaderUniforms[CCShaderUniformSinTime] getValue:&globalUniforms.sinTime];
681+
[_globalShaderUniforms[CCShaderUniformCosTime] getValue:&globalUniforms.cosTime];
682+
[_globalShaderUniforms[CCShaderUniformRandom01] getValue:&globalUniforms.random01];
683+
684+
void *buff = CCGraphicsBufferPushElements(_uniformBuffer, globalUniformBytes);
685+
memcpy(buff, &globalUniforms, globalUniformBytes);
686+
}
687+
#endif
688+
689+
// Execute the rendering commands.
657690
SortQueue(_queue);
658691
for(id<CCRenderCommand> command in _queue) [command invokeOnRenderer:self];
659692
[self bindBuffers:NO];
660693

661694
[_queue removeAllObjects];
662695

696+
// Commit the uniform buffers.
697+
[_uniformBuffer commit];
698+
699+
// Prepare the geometry buffers for use next time the renderer is reused.
663700
[_vertexBuffer prepare];
664701
[_elementBuffer prepare];
665702

666703
CCGL_DEBUG_POP_GROUP_MARKER();
667704
CC_CHECK_GL_ERROR_DEBUG();
668705

706+
// Reset the renderer's state.
669707
[self invalidateState];
670708
_threadsafe = YES;
671709
}

cocos2d/CCRenderer_private.h

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,25 @@
2828
#import "CCCache.h"
2929
#import "CCRenderDispatch.h"
3030

31+
#if __CC_METAL_SUPPORTED_AND_ENABLED
32+
33+
@class CCMetalContext;
34+
35+
// Struct used for packing the global uniforms.
36+
// NOTE: Must match the definition in CCShaders.metal!
37+
typedef struct CCGlobalUniforms {
38+
GLKMatrix4 projection;
39+
GLKMatrix4 projectionInv;
40+
GLKVector2 viewSize;
41+
GLKVector2 viewSizeInPixels;
42+
GLKVector4 time;
43+
GLKVector4 sinTime;
44+
GLKVector4 cosTime;
45+
GLKVector4 random01;
46+
} CCGlobalUniforms;
47+
48+
#endif
49+
3150
// TODO These should be made private to the module.
3251
extern id CCBLENDMODE_CACHE;
3352
extern id CCRENDERSTATE_CACHE;
@@ -112,7 +131,7 @@ typedef NS_ENUM(NSUInteger, CCRenderCommandDrawMode){
112131
typedef NS_ENUM(NSUInteger, CCGraphicsBufferType){
113132
CCGraphicsBufferTypeVertex,
114133
CCGraphicsBufferTypeIndex,
115-
// CCGraphicsBufferTypeUniform?
134+
CCGraphicsBufferTypeUniform,
116135
};
117136

118137

@@ -175,6 +194,7 @@ CCGraphicsBufferPushElements(CCGraphicsBuffer *buffer, size_t requestedCount)
175194
@public
176195
CCGraphicsBuffer *_vertexBuffer;
177196
CCGraphicsBuffer *_elementBuffer;
197+
CCGraphicsBuffer *_uniformBuffer; // Currently only used by the Metal renderer.
178198
id<CCGraphicsBufferBindings> _bufferBindings;
179199

180200
NSDictionary *_globalShaderUniforms;
@@ -187,9 +207,10 @@ CCGraphicsBufferPushElements(CCGraphicsBuffer *buffer, size_t requestedCount)
187207
__unsafe_unretained CCRenderState *_renderState;
188208
__unsafe_unretained CCRenderCommandDraw *_lastDrawCommand;
189209
BOOL _buffersBound;
190-
191-
// Currently used for associating a metal context with a given renderer.
192-
id _context;
210+
211+
#if __CC_METAL_SUPPORTED_AND_ENABLED
212+
CCMetalContext *_metalContext;
213+
#endif
193214
}
194215

195216
/// Current global shader uniform values.

cocos2d/CCShader.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ -(instancetype)initWithGLProgram:(GLuint)program uniformSetters:(NSDictionary *)
368368
return self;
369369
}
370370

371+
#if __CC_METAL_SUPPORTED_AND_ENABLED
371372
-(instancetype)initWithMetalVertexFunction:(id<MTLFunction>)vertexFunction fragmentFunction:(id<MTLFunction>)fragmentFunction
372373
{
373374
if((self = [super init])){
@@ -380,6 +381,7 @@ -(instancetype)initWithMetalVertexFunction:(id<MTLFunction>)vertexFunction fragm
380381

381382
return self;
382383
}
384+
#endif
383385

384386
-(instancetype)initWithVertexShaderSource:(NSString *)vertexSource fragmentShaderSource:(NSString *)fragmentSource
385387
{

cocos2d/Platforms/iOS/CCMetalSupport_Private.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@
3030

3131
#import "CCRenderer_Private.h"
3232

33+
// This is effectively hardcoded to 10 by Apple's docs and there is no API to query capabilities...
34+
// Seems like an oversight, but whatever.
35+
#define CCMTL_MAX_TEXTURES 10
36+
37+
// Maximum uniform bytes that can be passed to a shader.
38+
// This space is preallocated by all render states.
39+
#define CCMTL_MAX_UNIFORM_BYTES 32*4*4
40+
3341

3442
#if DEBUG
3543

cocos2d/Platforms/iOS/CCShaders.metal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef struct CCFragData {
1919
} CCFragData;
2020

2121
// Standard set of global uniform values.
22+
// NOTE: Must match the definition in CCRenderer_Private.h!
2223
typedef struct CCGlobalUniforms {
2324
float4x4 projection;
2425
float4x4 projectionInv;

0 commit comments

Comments
 (0)