Skip to content

Commit 92fdc15

Browse files
committed
Texture parameters and mipmaps for Metal.
1 parent 1d6ce21 commit 92fdc15

File tree

6 files changed

+138
-126
lines changed

6 files changed

+138
-126
lines changed

cocos2d/CCEffectRenderer.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ - (BOOL)setupGLResourcesWithSize:(CGSize)size
7373
// Create a new texture object for use as the color attachment of the new
7474
// FBO.
7575
_texture = [[CCTexture alloc] initWithData:nil pixelFormat:kRenderTargetDefaultPixelFormat pixelsWide:powW pixelsHigh:powH contentSizeInPixels:size contentScale:[CCDirector sharedDirector].contentScaleFactor];
76-
[_texture setAliasTexParameters];
76+
_texture.antialiased = NO;
7777

7878
// Save the old FBO binding so it can be restored after we create the new
7979
// one.

cocos2d/CCRenderTexture.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ -(void)create
195195
self.texture = texture;
196196
free(data);
197197

198-
[self.texture setAliasTexParameters];
198+
// Render textures are nearest filtered for legacy reasons.
199+
self.texture.antialiased = NO;
199200

200201
CCRenderDispatch(NO, ^{
201202
CCGL_DEBUG_PUSH_GROUP_MARKER("CCRenderTexture: Create");

cocos2d/CCTexture.m

Lines changed: 128 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,22 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
8989
#import "CCSpriteFrame.h"
9090

9191
#if __CC_METAL_SUPPORTED_AND_ENABLED
92+
9293
#import "CCMetalSupport_Private.h"
94+
95+
static const MTLPixelFormat MetalPixelFormats[] = {
96+
MTLPixelFormatRGBA8Unorm,
97+
MTLPixelFormatInvalid, //CCTexturePixelFormat_RGB888,
98+
MTLPixelFormatInvalid, //CCTexturePixelFormat_RGB565,
99+
MTLPixelFormatA8Unorm, //CCTexturePixelFormat_A8,
100+
MTLPixelFormatRG8Unorm, //CCTexturePixelFormat_I8,
101+
MTLPixelFormatInvalid, //CCTexturePixelFormat_AI88,
102+
MTLPixelFormatABGR4Unorm, //CCTexturePixelFormat_RGBA4444,
103+
MTLPixelFormatInvalid, //CCTexturePixelFormat_RGB5A1,
104+
MTLPixelFormatPVRTC_RGBA_4BPP, //CCTexturePixelFormat_PVRTC4,
105+
MTLPixelFormatPVRTC_RGBA_2BPP, //CCTexturePixelFormat_PVRTC2,
106+
};
107+
93108
#endif
94109

95110

@@ -213,43 +228,30 @@ + (id) textureWithFile:(NSString*)file
213228
- (id) initWithData:(const void*)data pixelFormat:(CCTexturePixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSizeInPixels:(CGSize)sizeInPixels contentScale:(CGFloat)contentScale
214229
{
215230
if((self = [super init])) {
216-
CCRenderDispatch(NO, ^{
217231
#if __CC_METAL_SUPPORTED_AND_ENABLED
218-
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
219-
id<MTLDevice> device = [CCMetalContext currentContext].device;
220-
221-
MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new];
222-
samplerDesc.minFilter = MTLSamplerMinMagFilterLinear;
223-
samplerDesc.magFilter = MTLSamplerMinMagFilterLinear;
224-
samplerDesc.mipFilter = MTLSamplerMipFilterNotMipmapped;
225-
samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
226-
samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
227-
228-
_metalSampler = [device newSamplerStateWithDescriptor:samplerDesc];
229-
230-
static const MTLPixelFormat metalFormats[] = {
231-
MTLPixelFormatRGBA8Unorm,
232-
MTLPixelFormatInvalid, //CCTexturePixelFormat_RGB888,
233-
MTLPixelFormatInvalid, //CCTexturePixelFormat_RGB565,
234-
MTLPixelFormatA8Unorm, //CCTexturePixelFormat_A8,
235-
MTLPixelFormatRG8Unorm, //CCTexturePixelFormat_I8,
236-
MTLPixelFormatInvalid, //CCTexturePixelFormat_AI88,
237-
MTLPixelFormatABGR4Unorm, //CCTexturePixelFormat_RGBA4444,
238-
MTLPixelFormatInvalid, //CCTexturePixelFormat_RGB5A1,
239-
MTLPixelFormatPVRTC_RGBA_4BPP, //CCTexturePixelFormat_PVRTC4,
240-
MTLPixelFormatPVRTC_RGBA_2BPP, //CCTexturePixelFormat_PVRTC2,
241-
};
242-
MTLPixelFormat metalFormat = metalFormats[pixelFormat];
243-
NSAssert(metalFormat != MTLPixelFormatInvalid, @"This texture format is not supported by Apple's Metal API.");
244-
245-
MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:metalFormat width:width height:height mipmapped:NO];
246-
_metalTexture = [device newTextureWithDescriptor:textureDesc];
247-
248-
NSUInteger bytesPerRow = width*[CCTexture bitsPerPixelForFormat:pixelFormat]/8;
249-
[_metalTexture replaceRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0 withBytes:data bytesPerRow:bytesPerRow];
250-
} else
232+
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
233+
id<MTLDevice> device = [CCMetalContext currentContext].device;
234+
235+
MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new];
236+
samplerDesc.minFilter = MTLSamplerMinMagFilterLinear;
237+
samplerDesc.magFilter = MTLSamplerMinMagFilterLinear;
238+
samplerDesc.mipFilter = MTLSamplerMipFilterNotMipmapped;
239+
samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
240+
samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
241+
242+
_metalSampler = [device newSamplerStateWithDescriptor:samplerDesc];
243+
244+
MTLPixelFormat metalFormat = MetalPixelFormats[pixelFormat];
245+
NSAssert(metalFormat != MTLPixelFormatInvalid, @"This texture format is not supported by Apple's Metal API.");
246+
247+
MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:metalFormat width:width height:height mipmapped:NO];
248+
_metalTexture = [device newTextureWithDescriptor:textureDesc];
249+
250+
NSUInteger bytesPerRow = width*[CCTexture bitsPerPixelForFormat:pixelFormat]/8;
251+
[_metalTexture replaceRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0 withBytes:data bytesPerRow:bytesPerRow];
252+
} else
251253
#endif
252-
{
254+
CCRenderDispatch(NO, ^{
253255
CCGL_DEBUG_PUSH_GROUP_MARKER("CCTexture: Init");
254256

255257
// XXX: 32 bits or POT textures uses UNPACK of 4 (is this correct ??? )
@@ -296,7 +298,6 @@ - (id) initWithData:(const void*)data pixelFormat:(CCTexturePixelFormat)pixelFor
296298
}
297299

298300
CCGL_DEBUG_POP_GROUP_MARKER();
299-
}
300301
});
301302

302303
_sizeInPixels = sizeInPixels;
@@ -393,9 +394,40 @@ -(CCSpriteFrame*) createSpriteFrame
393394

394395
- (void) setAntialiased:(BOOL)antialiased
395396
{
396-
_antialiased = antialiased;
397-
if (antialiased) [self setAntiAliasTexParameters];
398-
else [self setAliasTexParameters];
397+
if(_antialiased != antialiased){
398+
CCRenderDispatch(NO, ^{
399+
#if __CC_METAL_SUPPORTED_AND_ENABLED
400+
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
401+
CCMetalContext *context = [CCMetalContext currentContext];
402+
403+
MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new];
404+
samplerDesc.minFilter = samplerDesc.magFilter = (antialiased ? MTLSamplerMinMagFilterLinear : MTLSamplerMinMagFilterNearest);
405+
samplerDesc.mipFilter = (_hasMipmaps ? MTLSamplerMipFilterNearest : MTLSamplerMipFilterNotMipmapped);
406+
samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
407+
samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
408+
409+
_metalSampler = [context.device newSamplerStateWithDescriptor:samplerDesc];
410+
} else
411+
#endif
412+
{
413+
CCGL_DEBUG_PUSH_GROUP_MARKER("CCTexture: Set Alias Texture Parameters");
414+
415+
glBindTexture(GL_TEXTURE_2D, _name);
416+
417+
if(_hasMipmaps){
418+
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialiased ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST);
419+
} else {
420+
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialiased ? GL_LINEAR : GL_NEAREST);
421+
}
422+
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialiased ? GL_LINEAR : GL_NEAREST);
423+
424+
CCGL_DEBUG_POP_GROUP_MARKER();
425+
CC_CHECK_GL_ERROR_DEBUG();
426+
}
427+
});
428+
429+
_antialiased = antialiased;
430+
}
399431
}
400432

401433
@end
@@ -682,32 +714,77 @@ +(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied
682714
#pragma mark -
683715
#pragma mark CCTexture2D - GLFilter
684716

685-
#warning Not implemented for Metal.
686-
687717
//
688718
// Use to apply MIN/MAG filter
689719
//
690720
@implementation CCTexture (GLFilter)
691721

692722
-(void) generateMipmap
693723
{
694-
CCRenderDispatch(NO, ^{
695-
CCGL_DEBUG_PUSH_GROUP_MARKER("CCTexture: Generate Mipmap");
696-
697-
NSAssert( _width == CCNextPOT(_width) && _height == CCNextPOT(_height), @"Mimpap texture only works in POT textures");
698-
glBindTexture(GL_TEXTURE_2D, _name);
699-
glGenerateMipmap(GL_TEXTURE_2D);
700-
_hasMipmaps = YES;
701-
702-
CCGL_DEBUG_POP_GROUP_MARKER();
703-
});
724+
if(!_hasMipmaps){
725+
CCRenderDispatch(NO, ^{
726+
#if __CC_METAL_SUPPORTED_AND_ENABLED
727+
if([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIMetal){
728+
CCMetalContext *context = [CCMetalContext currentContext];
729+
730+
// Create a new blank texture.
731+
MTLPixelFormat metalFormat = MetalPixelFormats[_format];
732+
MTLTextureDescriptor *textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:metalFormat width:_width height:_height mipmapped:YES];
733+
id<MTLTexture> newTexture = [context.device newTextureWithDescriptor:textureDesc];
734+
735+
// Set up a command buffer for the blit operations.
736+
id<MTLCommandBuffer> blitCommands = [context.commandQueue commandBuffer];
737+
id<MTLBlitCommandEncoder> blitter = [blitCommands blitCommandEncoder];
738+
739+
// Copy in level 0.
740+
MTLOrigin origin = MTLOriginMake(0, 0, 0);
741+
MTLSize size = MTLSizeMake(_width, _height, 1);
742+
[blitter
743+
copyFromTexture:_metalTexture sourceSlice:0 sourceLevel:0 sourceOrigin:origin sourceSize:size
744+
toTexture:newTexture destinationSlice:0 destinationLevel:0 destinationOrigin:origin
745+
];
746+
747+
// Generate mipmaps and commit.
748+
[blitter generateMipmapsForTexture:newTexture];
749+
[blitter endEncoding];
750+
[blitCommands commit];
751+
752+
// Update sampler and texture.
753+
MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new];
754+
samplerDesc.minFilter = samplerDesc.magFilter = (_antialiased ? MTLSamplerMinMagFilterLinear : MTLSamplerMinMagFilterNearest);
755+
samplerDesc.mipFilter = MTLSamplerMipFilterNearest; // TODO trillinear?
756+
samplerDesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
757+
samplerDesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
758+
759+
_metalSampler = [context.device newSamplerStateWithDescriptor:samplerDesc];
760+
NSLog(@"Generate mipmaps. Replacing %p with %p.", _metalTexture, newTexture);
761+
_metalTexture = newTexture;
762+
} else
763+
#endif
764+
{
765+
CCGL_DEBUG_PUSH_GROUP_MARKER("CCTexture: Generate Mipmap");
766+
767+
NSAssert( _width == CCNextPOT(_width) && _height == CCNextPOT(_height), @"Mimpap texture only works in POT textures");
768+
glBindTexture(GL_TEXTURE_2D, _name);
769+
glGenerateMipmap(GL_TEXTURE_2D);
770+
771+
// Update the minification filter.
772+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _antialiased ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_NEAREST);
773+
774+
CCGL_DEBUG_POP_GROUP_MARKER();
775+
}
776+
});
777+
}
778+
779+
_hasMipmaps = YES;
704780
}
705781

706782
-(void) setTexParameters: (ccTexParams*) texParams
707783
{
708784
CCRenderDispatch(NO, ^{
709785
CCGL_DEBUG_PUSH_GROUP_MARKER("CCTexture: Set Texture Parameters");
710786

787+
NSAssert([CCConfiguration sharedConfiguration].graphicsAPI == CCGraphicsAPIGL, @"Not implemented for Metal.");
711788
NSAssert( (_width == CCNextPOT(_width) && _height == CCNextPOT(_height)) ||
712789
(texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE),
713790
@"GL_CLAMP_TO_EDGE should be used in NPOT dimensions");
@@ -723,47 +800,6 @@ -(void) setTexParameters: (ccTexParams*) texParams
723800
});
724801
}
725802

726-
-(void) setAliasTexParameters
727-
{
728-
CCRenderDispatch(NO, ^{
729-
CCGL_DEBUG_PUSH_GROUP_MARKER("CCTexture: Set Alias Texture Parameters");
730-
731-
glBindTexture(GL_TEXTURE_2D, _name );
732-
733-
if( ! _hasMipmaps ){
734-
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
735-
} else {
736-
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
737-
}
738-
739-
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
740-
CCGL_DEBUG_POP_GROUP_MARKER();
741-
CC_CHECK_GL_ERROR_DEBUG();
742-
});
743-
744-
_antialiased = NO;
745-
}
746-
747-
-(void) setAntiAliasTexParameters
748-
{
749-
CCRenderDispatch(NO, ^{
750-
CCGL_DEBUG_PUSH_GROUP_MARKER("CCTexture: Set Anti-alias Texture Parameters");
751-
752-
glBindTexture(GL_TEXTURE_2D, _name );
753-
754-
if( ! _hasMipmaps )
755-
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
756-
else
757-
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
758-
759-
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
760-
761-
CCGL_DEBUG_POP_GROUP_MARKER();
762-
CC_CHECK_GL_ERROR_DEBUG();
763-
});
764-
765-
_antialiased = YES;
766-
}
767803
@end
768804

769805

cocos2d/CCTexture_Private.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -129,25 +129,6 @@ typedef struct _ccTexParams {
129129
*/
130130
-(void) setTexParameters: (ccTexParams*) texParams;
131131

132-
/* sets antialias texture parameters:
133-
- GL_TEXTURE_MIN_FILTER = GL_LINEAR
134-
- GL_TEXTURE_MAG_FILTER = GL_LINEAR
135-
136-
@warning Calling this method could allocate additional texture memory.
137-
138-
*/
139-
- (void) setAntiAliasTexParameters;
140-
141-
/* sets alias texture parameters:
142-
- GL_TEXTURE_MIN_FILTER = GL_NEAREST
143-
- GL_TEXTURE_MAG_FILTER = GL_NEAREST
144-
145-
@warning Calling this method could allocate additional texture memory.
146-
147-
*/
148-
- (void) setAliasTexParameters;
149-
150-
151132
/* Generates mipmap images for the texture.
152133
It only works if the texture size is POT (power of 2).
153134
*/

cocos2d/CCTiledMapLayer.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ -(void) setupTiles
155155
// - easier to render
156156
// cons:
157157
// - difficult to scale / rotate / etc.
158-
[self.texture setAliasTexParameters];
158+
self.texture.antialiased = NO;
159159

160160
// Parse cocos2d properties
161161
[self parseInternalProperties];

cocos2d/Platforms/iOS/CCMetalSupport.m

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,6 @@ -(void)bind:(BOOL)bind
176176
@interface CCRenderStateMetal : CCRenderState @end
177177
@implementation CCRenderStateMetal {
178178
id<MTLRenderPipelineState> _renderPipelineState;
179-
180-
NSRange _textureRange;
181-
// TODO should be unretained once the sampler issue is fixed.
182-
id<MTLSamplerState> _samplers[CCMTL_MAX_TEXTURES];
183-
__unsafe_unretained id<MTLTexture> _textures[CCMTL_MAX_TEXTURES];
184179
}
185180

186181
// Using GL enums for CCBlendMode types should never have happened. Oops.
@@ -235,20 +230,17 @@ -(void)prepare
235230
pipelineStateDescriptor.colorAttachments[0] = colorDescriptor;
236231

237232
_renderPipelineState = [context.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:nil];
238-
239-
CCTexture *texture = _shaderUniforms[CCShaderUniformMainTexture] ?: [CCTexture none];
240-
_textureRange = NSMakeRange(0, 1);
241-
_samplers[0] = texture.metalSampler;
242-
_textures[0] = texture.metalTexture;
243233
}
244234
}
245235

246236
-(void)transitionRenderer:(CCRenderer *)renderer FromState:(CCRenderState *)previous
247237
{
248238
id<MTLRenderCommandEncoder> renderEncoder = CCMetalContextCurrent().currentRenderCommandEncoder;
249239
[renderEncoder setRenderPipelineState:_renderPipelineState];
250-
[renderEncoder setFragmentSamplerStates:_samplers withRange:_textureRange];
251-
[renderEncoder setFragmentTextures:_textures withRange:_textureRange];
240+
241+
CCTexture *mainTexture = _shaderUniforms[CCShaderUniformMainTexture];
242+
[renderEncoder setFragmentSamplerState:mainTexture.metalSampler atIndex:0];
243+
[renderEncoder setFragmentTexture:mainTexture.metalTexture atIndex:0];
252244
}
253245

254246
@end
@@ -281,6 +273,8 @@ -(void)invokeOnRenderer:(CCRenderer *)renderer
281273
[renderer setRenderState:_renderState];
282274
[renderEncoder drawIndexedPrimitives:MetalDrawModes[_mode] indexCount:_count indexType:MTLIndexTypeUInt16 indexBuffer:indexBuffer indexBufferOffset:2*_first];
283275
CCMTL_DEBUG_POP_GROUP_MARKER(renderEncoder);
276+
277+
CC_INCREMENT_GL_DRAWS(1);
284278
}
285279

286280
@end

0 commit comments

Comments
 (0)