Skip to content

Commit 2ddcc43

Browse files
committed
Make uniform dictionary copying behavior of CCRenderState explicit for immutability purposes. Fix a minor garbage creation issue with CCTTFLabel and CCRenderTexture.
1 parent 7d242d3 commit 2ddcc43

File tree

6 files changed

+46
-10
lines changed

6 files changed

+46
-10
lines changed

cocos2d/CCLabelTTF.m

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,12 @@ - (void) setTextureDirty
332332
-(CCRenderState *)renderState
333333
{
334334
if(_renderState == nil){
335+
// Allowing the uniforms to be copied speeds up the rendering by making the render state immutable.
336+
// Copy the uniforms if custom uniforms are not being used.
337+
BOOL copyUniforms = self.hasDefaultShaderUniforms;
338+
335339
// Create an uncached renderstate so the texture can be released before the renderstate cache is flushed.
336-
_renderState = [[CCRenderState alloc] initWithBlendMode:_blendMode shader:_shader shaderUniforms:self.shaderUniforms];
340+
_renderState = [[CCRenderState alloc] initWithBlendMode:_blendMode shader:_shader shaderUniforms:self.shaderUniforms copyUniforms:copyUniforms];
337341
}
338342

339343
return _renderState;

cocos2d/CCNode.m

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1765,7 +1765,7 @@ -(CCRenderState *)renderState
17651765
_shaderUniforms = nil;
17661766
} else {
17671767
// Since the node has unique uniforms, it cannot be batched or use the fast path.
1768-
_renderState = [[CCRenderState alloc] initWithBlendMode:_blendMode shader:_shader shaderUniforms:_shaderUniforms];
1768+
_renderState = [[CCRenderState alloc] initWithBlendMode:_blendMode shader:_shader shaderUniforms:_shaderUniforms copyUniforms:NO];
17691769
}
17701770
}
17711771

@@ -1788,6 +1788,19 @@ -(CCBlendMode *)blendMode
17881788
return _blendMode;
17891789
}
17901790

1791+
-(BOOL)hasDefaultShaderUniforms
1792+
{
1793+
CCTexture *texture = (_texture ?: [CCTexture none]);
1794+
if(CheckDefaultUniforms(_shaderUniforms, texture)){
1795+
// If the uniform dictionary was set, it was the default. Throw it away.
1796+
_shaderUniforms = nil;
1797+
1798+
return YES;
1799+
} else {
1800+
return NO;
1801+
}
1802+
}
1803+
17911804
-(NSMutableDictionary *)shaderUniforms
17921805
{
17931806
if(_shaderUniforms == nil){

cocos2d/CCNode_Private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ CGAffineTransform CGAffineTransformMakeRigid(CGPoint translate, CGFloat radians)
4343
CCTexture *_texture;
4444
}
4545

46+
/// Returns true if the node is not using custom uniforms.
47+
-(BOOL)hasDefaultShaderUniforms;
48+
4649
/// Cache and return the current render state.
4750
/// Should be set to nil whenever changing a property that affects the renderstate.
4851
@property(nonatomic, strong) CCRenderState *renderState;

cocos2d/CCRenderTexture.m

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,12 @@ @implementation CCRenderTextureSprite
4949
-(CCRenderState *)renderState
5050
{
5151
if(_renderState == nil){
52+
// Allowing the uniforms to be copied speeds up the rendering by making the render state immutable.
53+
// Copy the uniforms if custom uniforms are not being used.
54+
BOOL copyUniforms = self.hasDefaultShaderUniforms;
55+
5256
// Create an uncached renderstate so the texture can be released before the renderstate cache is flushed.
53-
_renderState = [[CCRenderState alloc] initWithBlendMode:_blendMode shader:_shader shaderUniforms:self.shaderUniforms];
57+
_renderState = [[CCRenderState alloc] initWithBlendMode:_blendMode shader:_shader shaderUniforms:self.shaderUniforms copyUniforms:copyUniforms];
5458
}
5559

5660
return _renderState;

cocos2d/CCRenderer.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,12 @@ extern const NSString *CCBlendEquationAlpha;
172172
/// Create a cached blending mode for a given blending mode, shader and main texture.
173173
+(instancetype)renderStateWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader mainTexture:(CCTexture *)mainTexture;
174174

175+
/// Create an uncached blending mode for a given blending mode, shader and set of uncopied uniform values.
176+
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms __deprecated;
177+
175178
/// Create an uncached blending mode for a given blending mode, shader and set of uniform values.
176-
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms;
179+
/// Allowing the uniform dictionary to be copied allows the render state to be immutable and used more optimally.
180+
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms copyUniforms:(BOOL)copyUniforms;
177181

178182
@end
179183

cocos2d/CCRenderer.m

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ -(void)flush
263263

264264
@implementation CCRenderState {
265265
CCTexture *_mainTexture;
266+
BOOL _immutable;
266267

267268
@public
268269
CCBlendMode *_blendMode;
@@ -280,11 +281,19 @@ +(void)initialize
280281
}
281282

282283
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms
284+
{
285+
return [self initWithBlendMode:blendMode shader:shader shaderUniforms:shaderUniforms copyUniforms:NO];
286+
}
287+
288+
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms copyUniforms:(BOOL)copyUniforms
283289
{
284290
if((self = [super init])){
285291
_blendMode = blendMode;
286292
_shader = shader;
287-
_shaderUniforms = shaderUniforms;
293+
_shaderUniforms = (copyUniforms ? [shaderUniforms copy] : shaderUniforms);
294+
295+
// The renderstate as a whole is immutable if the uniforms are copied.
296+
_immutable = copyUniforms;
288297
}
289298

290299
return self;
@@ -297,25 +306,24 @@ +(instancetype)renderStateWithBlendMode:(CCBlendMode *)blendMode shader:(CCShade
297306
mainTexture = [CCTexture none];
298307
}
299308

300-
CCRenderState *renderState = [[self alloc] initWithBlendMode:blendMode shader:shader shaderUniforms:@{CCShaderUniformMainTexture: mainTexture}];
309+
CCRenderState *renderState = [[self alloc] initWithBlendMode:blendMode shader:shader shaderUniforms:@{CCShaderUniformMainTexture: mainTexture} copyUniforms:YES];
301310
renderState->_mainTexture = mainTexture;
302311

303312
return [CCRENDERSTATE_CACHE objectForKey:renderState];
304313
}
305314

306315
-(id)copyWithZone:(NSZone *)zone
307316
{
308-
NSDictionary *shaderUniforms = [_shaderUniforms copy];
309-
if(shaderUniforms == _shaderUniforms){
317+
if(_immutable){
310318
return self;
311319
} else {
312-
return [[CCRenderState allocWithZone:zone] initWithBlendMode:_blendMode shader:_shader shaderUniforms:shaderUniforms];
320+
return [[CCRenderState allocWithZone:zone] initWithBlendMode:_blendMode shader:_shader shaderUniforms:_shaderUniforms copyUniforms:YES];
313321
}
314322
}
315323

316324
-(NSUInteger)hash
317325
{
318-
NSAssert(_mainTexture, @"Attempting to cache a renderstate without a mainTexture value.");
326+
NSAssert(_mainTexture, @"Attempting to cache a renderstate that was nort created with renderStateWithBlendMode.");
319327

320328
// Not great, but acceptable. All values are unique by pointer.
321329
return ((NSUInteger)_blendMode ^ (NSUInteger)_shader ^ (NSUInteger)_mainTexture);

0 commit comments

Comments
 (0)