Branimir Karadžić 10 years ago
parent
commit
cdbe689d93
2 changed files with 127 additions and 99 deletions
  1. 42 35
      src/renderer_mtl.h
  2. 85 64
      src/renderer_mtl.mm

+ 42 - 35
src/renderer_mtl.h

@@ -19,9 +19,9 @@
 
 
 namespace bgfx { namespace mtl
 namespace bgfx { namespace mtl
 {
 {
-		//c++ wrapper
-		// objects with creation functions starting with 'new' has a refcount 1 after creation, object must be destroyed with release.
-		// commandBuffer, commandEncoders are autoreleased objects. Needs AutoreleasePool!
+	// c++ wrapper
+	// objects with creation functions starting with 'new' has a refcount 1 after creation, object must be destroyed with release.
+	// commandBuffer, commandEncoders are autoreleased objects. Needs AutoreleasePool!
 
 
 #define MTL_CLASS(name) \
 #define MTL_CLASS(name) \
 	class name \
 	class name \
@@ -35,7 +35,6 @@ namespace bgfx { namespace mtl
 
 
 		typedef void (*mtlCallback)(void* userData);
 		typedef void (*mtlCallback)(void* userData);
 
 
-		//TODO: ??MTLBlitCommandEncoder??
 	MTL_CLASS(Buffer)
 	MTL_CLASS(Buffer)
 		void* contents()
 		void* contents()
 		{
 		{
@@ -50,7 +49,7 @@ namespace bgfx { namespace mtl
 
 
 	MTL_CLASS(CommandBuffer)
 	MTL_CLASS(CommandBuffer)
 		// Creating Command Encoders
 		// Creating Command Encoders
-		id<MTLRenderCommandEncoder> renderCommandEncoderWithDescriptor( MTLRenderPassDescriptor *_renderPassDescriptor){
+		id<MTLRenderCommandEncoder> renderCommandEncoderWithDescriptor( MTLRenderPassDescriptor* _renderPassDescriptor){
 			return [m_obj renderCommandEncoderWithDescriptor:_renderPassDescriptor];
 			return [m_obj renderCommandEncoderWithDescriptor:_renderPassDescriptor];
 		}
 		}
 
 
@@ -165,38 +164,38 @@ namespace bgfx { namespace mtl
 			return [m_obj newBufferWithLength:_length options:_options ];
 			return [m_obj newBufferWithLength:_length options:_options ];
 		}
 		}
 
 
-		id<MTLBuffer> newBufferWithBytes(const void *_pointer, NSUInteger _length, MTLResourceOptions _options)
+		id<MTLBuffer> newBufferWithBytes(const void* _pointer, NSUInteger _length, MTLResourceOptions _options)
 		{
 		{
 			return [m_obj newBufferWithBytes:_pointer length:_length options:_options];
 			return [m_obj newBufferWithBytes:_pointer length:_length options:_options];
 		}
 		}
 
 
-		id<MTLTexture> newTextureWithDescriptor(MTLTextureDescriptor * _descriptor)
+		id<MTLTexture> newTextureWithDescriptor(MTLTextureDescriptor* _descriptor)
 		{
 		{
 			return [m_obj newTextureWithDescriptor:_descriptor];
 			return [m_obj newTextureWithDescriptor:_descriptor];
 		}
 		}
 
 
-		id<MTLSamplerState> newSamplerStateWithDescriptor(MTLSamplerDescriptor * _descriptor)
+		id<MTLSamplerState> newSamplerStateWithDescriptor(MTLSamplerDescriptor* _descriptor)
 		{
 		{
 			return [m_obj newSamplerStateWithDescriptor:_descriptor];
 			return [m_obj newSamplerStateWithDescriptor:_descriptor];
 		}
 		}
 
 
 		// Creating Command Objects Needed to Render Graphics
 		// Creating Command Objects Needed to Render Graphics
-		id<MTLDepthStencilState> newDepthStencilStateWithDescriptor(MTLDepthStencilDescriptor * _descriptor)
+		id<MTLDepthStencilState> newDepthStencilStateWithDescriptor(MTLDepthStencilDescriptor* _descriptor)
 		{
 		{
 			return [m_obj newDepthStencilStateWithDescriptor:_descriptor];
 			return [m_obj newDepthStencilStateWithDescriptor:_descriptor];
 		}
 		}
 
 
-		id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor *_descriptor)
+		id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor* _descriptor)
 		{
 		{
-			NSError *error;
+			NSError* error;
 			id <MTLRenderPipelineState> state = [m_obj newRenderPipelineStateWithDescriptor:_descriptor error:&error];
 			id <MTLRenderPipelineState> state = [m_obj newRenderPipelineStateWithDescriptor:_descriptor error:&error];
 			BX_WARN(error==NULL,"newRenderPipelineStateWithDescriptor failed:%s", [error.localizedDescription UTF8String] );
 			BX_WARN(error==NULL,"newRenderPipelineStateWithDescriptor failed:%s", [error.localizedDescription UTF8String] );
 			return state;
 			return state;
 		}
 		}
 
 
-		id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor *_descriptor, MTLPipelineOption _options, MTLRenderPipelineReflection** _reflection)
+		id <MTLRenderPipelineState> newRenderPipelineStateWithDescriptor(MTLRenderPipelineDescriptor* _descriptor, MTLPipelineOption _options, MTLRenderPipelineReflection** _reflection)
 		{
 		{
-			NSError *error;
+			NSError* error;
 			id <MTLRenderPipelineState> state = [m_obj newRenderPipelineStateWithDescriptor:_descriptor options:_options reflection:_reflection error:&error];
 			id <MTLRenderPipelineState> state = [m_obj newRenderPipelineStateWithDescriptor:_descriptor options:_options reflection:_reflection error:&error];
 
 
 			BX_WARN(error==NULL,"newRenderPipelineStateWithDescriptor failed:%s", [error.localizedDescription UTF8String] );
 			BX_WARN(error==NULL,"newRenderPipelineStateWithDescriptor failed:%s", [error.localizedDescription UTF8String] );
@@ -206,7 +205,7 @@ namespace bgfx { namespace mtl
 		// Creating Command Objects Needed to Perform Computational Tasks
 		// Creating Command Objects Needed to Perform Computational Tasks
 		id <MTLComputePipelineState> newComputePipelineStateWithFunction(id <MTLFunction> _computeFunction)
 		id <MTLComputePipelineState> newComputePipelineStateWithFunction(id <MTLFunction> _computeFunction)
 		{
 		{
-			NSError *error;
+			NSError* error;
 			id <MTLComputePipelineState> state = [m_obj newComputePipelineStateWithFunction:_computeFunction error:&error];
 			id <MTLComputePipelineState> state = [m_obj newComputePipelineStateWithFunction:_computeFunction error:&error];
 			BX_WARN(error==NULL,"newComputePipelineStateWithFunction failed:%s", [error.localizedDescription UTF8String] );
 			BX_WARN(error==NULL,"newComputePipelineStateWithFunction failed:%s", [error.localizedDescription UTF8String] );
 			return state;
 			return state;
@@ -214,7 +213,7 @@ namespace bgfx { namespace mtl
 	MTL_CLASS_END
 	MTL_CLASS_END
 
 
 	MTL_CLASS(Function)
 	MTL_CLASS(Function)
-		NSArray *vertexAttributes() { return m_obj.vertexAttributes; }
+		NSArray* vertexAttributes() { return m_obj.vertexAttributes; }
 	MTL_CLASS_END
 	MTL_CLASS_END
 
 
 	MTL_CLASS(Library)
 	MTL_CLASS(Library)
@@ -345,13 +344,13 @@ namespace bgfx { namespace mtl
 
 
 	MTL_CLASS(Texture)
 	MTL_CLASS(Texture)
 		// Copying Data into a Texture Image
 		// Copying Data into a Texture Image
-		void replaceRegion(MTLRegion _region, NSUInteger _level, NSUInteger _slice, const void *_pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage)
+		void replaceRegion(MTLRegion _region, NSUInteger _level, NSUInteger _slice, const void* _pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage)
 		{
 		{
 			[m_obj replaceRegion:_region mipmapLevel:_level slice:_slice withBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage];
 			[m_obj replaceRegion:_region mipmapLevel:_level slice:_slice withBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage];
 		}
 		}
 
 
 		// Copying Data from a Texture Image
 		// Copying Data from a Texture Image
-		void getBytes(void *_pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage, MTLRegion _region, NSUInteger _mipmapLevel, NSUInteger _slice)
+		void getBytes(void* _pixelBytes, NSUInteger _bytesPerRow, NSUInteger _bytesPerImage, MTLRegion _region, NSUInteger _mipmapLevel, NSUInteger _slice)
 		{
 		{
 			[m_obj getBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage fromRegion:_region mipmapLevel:_mipmapLevel slice:_slice];
 			[m_obj getBytes:_pixelBytes bytesPerRow:_bytesPerRow bytesPerImage:_bytesPerImage fromRegion:_region mipmapLevel:_mipmapLevel slice:_slice];
 		}
 		}
@@ -384,15 +383,16 @@ namespace bgfx { namespace mtl
 	typedef id<MTLRenderPipelineState> RenderPipelineState;
 	typedef id<MTLRenderPipelineState> RenderPipelineState;
 	typedef id<MTLSamplerState> SamplerState;
 	typedef id<MTLSamplerState> SamplerState;
 
 
-		//descriptors
+	//descriptors
 	//NOTE: [class new] is same as [[class alloc] init]
 	//NOTE: [class new] is same as [[class alloc] init]
 	typedef MTLRenderPipelineDescriptor* RenderPipelineDescriptor;
 	typedef MTLRenderPipelineDescriptor* RenderPipelineDescriptor;
-	RenderPipelineDescriptor newRenderPipelineDescriptor()
+
+	inline RenderPipelineDescriptor newRenderPipelineDescriptor()
 	{
 	{
 		return [MTLRenderPipelineDescriptor new];
 		return [MTLRenderPipelineDescriptor new];
 	}
 	}
 
 
-	void reset(RenderPipelineDescriptor _desc)
+	inline void reset(RenderPipelineDescriptor _desc)
 	{
 	{
 		[_desc reset];
 		[_desc reset];
 	}
 	}
@@ -400,13 +400,15 @@ namespace bgfx { namespace mtl
 	typedef MTLRenderPipelineColorAttachmentDescriptor* RenderPipelineColorAttachmentDescriptor;
 	typedef MTLRenderPipelineColorAttachmentDescriptor* RenderPipelineColorAttachmentDescriptor;
 
 
 	typedef MTLDepthStencilDescriptor* DepthStencilDescriptor;
 	typedef MTLDepthStencilDescriptor* DepthStencilDescriptor;
-	MTLDepthStencilDescriptor* newDepthStencilDescriptor()
+
+	inline MTLDepthStencilDescriptor* newDepthStencilDescriptor()
 	{
 	{
 		return [MTLDepthStencilDescriptor new];
 		return [MTLDepthStencilDescriptor new];
 	}
 	}
 
 
 	typedef MTLStencilDescriptor* StencilDescriptor;
 	typedef MTLStencilDescriptor* StencilDescriptor;
-	MTLStencilDescriptor* newStencilDescriptor()
+
+	inline MTLStencilDescriptor* newStencilDescriptor()
 	{
 	{
 		return [MTLStencilDescriptor new];
 		return [MTLStencilDescriptor new];
 	}
 	}
@@ -416,30 +418,34 @@ namespace bgfx { namespace mtl
 	typedef MTLRenderPassStencilAttachmentDescriptor* RenderPassStencilAttachmentDescriptor;
 	typedef MTLRenderPassStencilAttachmentDescriptor* RenderPassStencilAttachmentDescriptor;
 
 
 	typedef MTLRenderPassDescriptor* RenderPassDescriptor;
 	typedef MTLRenderPassDescriptor* RenderPassDescriptor;
-	MTLRenderPassDescriptor* newRenderPassDescriptor()
+
+	inline MTLRenderPassDescriptor* newRenderPassDescriptor()
 	{
 	{
 		return [MTLRenderPassDescriptor new];
 		return [MTLRenderPassDescriptor new];
 	}
 	}
 
 
 	typedef MTLVertexDescriptor* VertexDescriptor;
 	typedef MTLVertexDescriptor* VertexDescriptor;
-	MTLVertexDescriptor* newVertexDescriptor()
+
+	inline MTLVertexDescriptor* newVertexDescriptor()
 	{
 	{
 		return [MTLVertexDescriptor new];
 		return [MTLVertexDescriptor new];
 	}
 	}
 
 
-	void reset(VertexDescriptor _desc)
+	inline void reset(VertexDescriptor _desc)
 	{
 	{
 		[_desc reset];
 		[_desc reset];
 	}
 	}
 
 
 	typedef MTLSamplerDescriptor* SamplerDescriptor;
 	typedef MTLSamplerDescriptor* SamplerDescriptor;
-	MTLSamplerDescriptor* newSamplerDescriptor()
+
+	inline MTLSamplerDescriptor* newSamplerDescriptor()
 	{
 	{
 		return [MTLSamplerDescriptor new];
 		return [MTLSamplerDescriptor new];
 	}
 	}
 
 
 	typedef MTLTextureDescriptor* TextureDescriptor;
 	typedef MTLTextureDescriptor* TextureDescriptor;
-	MTLTextureDescriptor* newTextureDescriptor()
+
+	inline MTLTextureDescriptor* newTextureDescriptor()
 	{
 	{
 		return [MTLTextureDescriptor new];
 		return [MTLTextureDescriptor new];
 	}
 	}
@@ -447,27 +453,29 @@ namespace bgfx { namespace mtl
 	typedef MTLRenderPipelineReflection* RenderPipelineReflection;
 	typedef MTLRenderPipelineReflection* RenderPipelineReflection;
 
 
 	//helper functions
 	//helper functions
-	void release(NSObject* _obj)
+	inline void release(NSObject* _obj)
 	{
 	{
 		[_obj release];
 		[_obj release];
 	}
 	}
 
 
-	void retain(NSObject* _obj)
+	inline void retain(NSObject* _obj)
 	{
 	{
 		[_obj retain];
 		[_obj retain];
 	}
 	}
 
 
-	const char* utf8String(NSString* _str)
+	inline const char* utf8String(NSString* _str)
 	{
 	{
 		return [_str UTF8String];
 		return [_str UTF8String];
 	}
 	}
 
 
-#define MTL_RELEASE(_obj)	\
-	[_obj release]; \
-	_obj = nil;
+#define MTL_RELEASE(_obj) \
+			BX_MACRO_BLOCK_BEGIN \
+				[_obj release]; \
+				_obj = nil; \
+			BX_MACRO_BLOCK_END
 
 
 #if BX_PLATFORM_IOS
 #if BX_PLATFORM_IOS
-	bool OsVersionEqualOrGreater(const char* _version)
+	inline bool OsVersionEqualOrGreater(const char* _version)
 	{
 	{
 		return ([[[UIDevice currentDevice] systemVersion] compare:@(_version) options:NSNumericSearch] != NSOrderedAscending);
 		return ([[[UIDevice currentDevice] systemVersion] compare:@(_version) options:NSNumericSearch] != NSOrderedAscending);
 	}
 	}
@@ -587,7 +595,6 @@ namespace bgfx { namespace mtl
 		Function m_function;
 		Function m_function;
 	};
 	};
 
 
-
 	struct ProgramMtl
 	struct ProgramMtl
 	{
 	{
 		ProgramMtl()
 		ProgramMtl()

+ 85 - 64
src/renderer_mtl.mm

@@ -768,14 +768,14 @@ namespace bgfx { namespace mtl
 		uint32_t vertexUniformBufferSize = program.m_vshConstantBufferSize;
 		uint32_t vertexUniformBufferSize = program.m_vshConstantBufferSize;
 		uint32_t fragmentUniformBufferSize = program.m_fshConstantBufferSize;
 		uint32_t fragmentUniformBufferSize = program.m_fshConstantBufferSize;
 
 
-		if ( vertexUniformBufferSize )
+		if (vertexUniformBufferSize )
 		{
 		{
 			m_uniformBufferVertexOffset = BX_ALIGN_MASK(m_uniformBufferVertexOffset, program.m_vshConstantBufferAlignmentMask);
 			m_uniformBufferVertexOffset = BX_ALIGN_MASK(m_uniformBufferVertexOffset, program.m_vshConstantBufferAlignmentMask);
 			rce.setVertexBuffer(m_uniformBuffer, m_uniformBufferVertexOffset, 0);
 			rce.setVertexBuffer(m_uniformBuffer, m_uniformBufferVertexOffset, 0);
 		}
 		}
 
 
 		m_uniformBufferFragmentOffset = m_uniformBufferVertexOffset + vertexUniformBufferSize;
 		m_uniformBufferFragmentOffset = m_uniformBufferVertexOffset + vertexUniformBufferSize;
-		if ( fragmentUniformBufferSize )
+		if (fragmentUniformBufferSize )
 		{
 		{
 			m_uniformBufferFragmentOffset = BX_ALIGN_MASK(m_uniformBufferFragmentOffset, program.m_fshConstantBufferAlignmentMask);
 			m_uniformBufferFragmentOffset = BX_ALIGN_MASK(m_uniformBufferFragmentOffset, program.m_fshConstantBufferAlignmentMask);
 			rce.setFragmentBuffer(m_uniformBuffer, m_uniformBufferFragmentOffset, 0);
 			rce.setFragmentBuffer(m_uniformBuffer, m_uniformBufferFragmentOffset, 0);
@@ -869,13 +869,15 @@ namespace bgfx { namespace mtl
 
 
 			m_textureDescriptor.pixelFormat = MTLPixelFormatDepth32Float;
 			m_textureDescriptor.pixelFormat = MTLPixelFormatDepth32Float;
 
 
-			m_textureDescriptor.width = width;
+			m_textureDescriptor.width  = width;
 			m_textureDescriptor.height = height;
 			m_textureDescriptor.height = height;
-			m_textureDescriptor.depth = 1;
+			m_textureDescriptor.depth  = 1;
 			m_textureDescriptor.mipmapLevelCount = 1;
 			m_textureDescriptor.mipmapLevelCount = 1;
 			m_textureDescriptor.sampleCount = 1;
 			m_textureDescriptor.sampleCount = 1;
 			m_textureDescriptor.arrayLength = 1;
 			m_textureDescriptor.arrayLength = 1;
-			//m_textureDescriptor.resourceOptions = 0;
+			m_textureDescriptor.resourceOptions = MTLResourceStorageModePrivate;
+			m_textureDescriptor.cpuCacheMode    = MTLCPUCacheModeDefaultCache;
+			m_textureDescriptor.storageMode     = MTLStorageModePrivate;
 
 
 			if (NULL != m_backBufferDepth)
 			if (NULL != m_backBufferDepth)
 			{
 			{
@@ -883,9 +885,8 @@ namespace bgfx { namespace mtl
 			}
 			}
 			m_backBufferDepth = m_device.newTextureWithDescriptor(m_textureDescriptor);
 			m_backBufferDepth = m_device.newTextureWithDescriptor(m_textureDescriptor);
 
 
+#if 0
 			m_textureDescriptor.pixelFormat = MTLPixelFormatStencil8;
 			m_textureDescriptor.pixelFormat = MTLPixelFormatStencil8;
-			m_textureDescriptor.width = width;
-			m_textureDescriptor.height = height;
 
 
 			if (NULL != m_backBufferStencil)
 			if (NULL != m_backBufferStencil)
 			{
 			{
@@ -893,6 +894,9 @@ namespace bgfx { namespace mtl
 			}
 			}
 
 
 			m_backBufferStencil = m_device.newTextureWithDescriptor(m_textureDescriptor);
 			m_backBufferStencil = m_device.newTextureWithDescriptor(m_textureDescriptor);
+#else
+			m_backBufferStencil = m_backBufferDepth;
+#endif // 0
 
 
 			bx::HashMurmur2A murmur;
 			bx::HashMurmur2A murmur;
 			murmur.begin();
 			murmur.begin();
@@ -1334,11 +1338,11 @@ namespace bgfx { namespace mtl
 		memset(m_attributes, 0xff, sizeof(m_attributes) );
 		memset(m_attributes, 0xff, sizeof(m_attributes) );
 		uint32_t used = 0;
 		uint32_t used = 0;
 		uint32_t instUsed = 0;
 		uint32_t instUsed = 0;
-		if ( NULL != _vsh->m_function.m_obj )
+		if (NULL != _vsh->m_function.m_obj )
 		{
 		{
 			for (MTLVertexAttribute* attrib in _vsh->m_function.m_obj.vertexAttributes)
 			for (MTLVertexAttribute* attrib in _vsh->m_function.m_obj.vertexAttributes)
 			{
 			{
-				if ( attrib.active )
+				if (attrib.active )
 				{
 				{
 					const char* name = utf8String(attrib.name);
 					const char* name = utf8String(attrib.name);
 					uint32_t loc = (uint32_t)attrib.attributeIndex;
 					uint32_t loc = (uint32_t)attrib.attributeIndex;
@@ -1366,7 +1370,7 @@ namespace bgfx { namespace mtl
 			}
 			}
 		}
 		}
 		m_used[used] = Attrib::Count;
 		m_used[used] = Attrib::Count;
-		m_instanceData[instUsed] = 0xffff;
+		m_instanceData[instUsed] = UINT16_MAX;
 	}
 	}
 
 
 	void ProgramMtl::destroy()
 	void ProgramMtl::destroy()
@@ -1432,7 +1436,9 @@ namespace bgfx { namespace mtl
 		murmur.add(_state);
 		murmur.add(_state);
 		murmur.add(independentBlendEnable ? _rgba : 0);
 		murmur.add(independentBlendEnable ? _rgba : 0);
 		if (!isValid(_fbHandle) )
 		if (!isValid(_fbHandle) )
+		{
 			murmur.add(s_renderMtl->m_backBufferPixelFormatHash);
 			murmur.add(s_renderMtl->m_backBufferPixelFormatHash);
+		}
 		else
 		else
 		{
 		{
 			FrameBufferMtl& frameBuffer = s_renderMtl->m_frameBuffers[_fbHandle.idx];
 			FrameBufferMtl& frameBuffer = s_renderMtl->m_frameBuffers[_fbHandle.idx];
@@ -1443,17 +1449,17 @@ namespace bgfx { namespace mtl
 		uint32_t hash = murmur.end();
 		uint32_t hash = murmur.end();
 
 
 		RenderPipelineState rps = m_renderPipelineStateCache.find(hash);
 		RenderPipelineState rps = m_renderPipelineStateCache.find(hash);
-		if ( NULL == rps )
+		if (NULL == rps)
 		{
 		{
-			RenderPipelineDescriptor& 	pipelineDesc = s_renderMtl->m_renderPipelineDescriptor;
-			reset(pipelineDesc);
+			RenderPipelineDescriptor& pd = s_renderMtl->m_renderPipelineDescriptor;
+			reset(pd);
 			uint32_t frameBufferAttachment = 1;
 			uint32_t frameBufferAttachment = 1;
 
 
 			if (!isValid(_fbHandle) )
 			if (!isValid(_fbHandle) )
 			{
 			{
-				pipelineDesc.colorAttachments[0].pixelFormat = s_renderMtl->m_drawable.texture.pixelFormat;
-				pipelineDesc.depthAttachmentPixelFormat = s_renderMtl->m_backBufferDepth.m_obj.pixelFormat;
-				pipelineDesc.stencilAttachmentPixelFormat = s_renderMtl->m_backBufferStencil.m_obj.pixelFormat;
+				pd.colorAttachments[0].pixelFormat = s_renderMtl->m_drawable.texture.pixelFormat;
+				pd.depthAttachmentPixelFormat      = s_renderMtl->m_backBufferDepth.m_obj.pixelFormat;
+				pd.stencilAttachmentPixelFormat    = MTLPixelFormatInvalid; //s_renderMtl->m_backBufferStencil.m_obj.pixelFormat;
 			}
 			}
 			else
 			else
 			{
 			{
@@ -1463,15 +1469,17 @@ namespace bgfx { namespace mtl
 				for (uint32_t ii = 0; ii < frameBuffer.m_num; ++ii)
 				for (uint32_t ii = 0; ii < frameBuffer.m_num; ++ii)
 				{
 				{
 					const TextureMtl& texture = s_renderMtl->m_textures[frameBuffer.m_colorHandle[ii].idx];
 					const TextureMtl& texture = s_renderMtl->m_textures[frameBuffer.m_colorHandle[ii].idx];
-					pipelineDesc.colorAttachments[ii].pixelFormat = texture.m_ptr.m_obj.pixelFormat;
+					pd.colorAttachments[ii].pixelFormat = texture.m_ptr.m_obj.pixelFormat;
 				}
 				}
 
 
 				if (isValid(frameBuffer.m_depthHandle))
 				if (isValid(frameBuffer.m_depthHandle))
 				{
 				{
 					const TextureMtl& texture = s_renderMtl->m_textures[frameBuffer.m_depthHandle.idx];
 					const TextureMtl& texture = s_renderMtl->m_textures[frameBuffer.m_depthHandle.idx];
-					pipelineDesc.depthAttachmentPixelFormat = texture.m_ptr.m_obj.pixelFormat;
-					if ( NULL != texture.m_ptrStencil)
-						pipelineDesc.stencilAttachmentPixelFormat = texture.m_ptrStencil.m_obj.pixelFormat;
+					pd.depthAttachmentPixelFormat = texture.m_ptr.m_obj.pixelFormat;
+					if (NULL != texture.m_ptrStencil)
+					{
+						pd.stencilAttachmentPixelFormat = MTLPixelFormatInvalid; //texture.m_ptrStencil.m_obj.pixelFormat;
+					}
 					//todo: stencil attachment should be the same as depth for packed depth/stencil
 					//todo: stencil attachment should be the same as depth for packed depth/stencil
 				}
 				}
 			}
 			}
@@ -1493,17 +1501,17 @@ namespace bgfx { namespace mtl
 
 
 			for (uint32_t ii = 0; ii < (independentBlendEnable ? 1 : frameBufferAttachment); ++ii)
 			for (uint32_t ii = 0; ii < (independentBlendEnable ? 1 : frameBufferAttachment); ++ii)
 			{
 			{
-				RenderPipelineColorAttachmentDescriptor drt = pipelineDesc.colorAttachments[ii];
+				RenderPipelineColorAttachmentDescriptor drt = pd.colorAttachments[ii];
 
 
 				drt.blendingEnabled = !!(BGFX_STATE_BLEND_MASK & _state);
 				drt.blendingEnabled = !!(BGFX_STATE_BLEND_MASK & _state);
 
 
-				drt.sourceRGBBlendFactor      = s_blendFactor[srcRGB][0];
-				drt.destinationRGBBlendFactor = s_blendFactor[dstRGB][0];
-				drt.rgbBlendOperation        =	s_blendEquation[equRGB];
+				drt.sourceRGBBlendFactor        = s_blendFactor[srcRGB][0];
+				drt.destinationRGBBlendFactor   = s_blendFactor[dstRGB][0];
+				drt.rgbBlendOperation           = s_blendEquation[equRGB];
 
 
-				drt.sourceAlphaBlendFactor		= s_blendFactor[srcA][1];
+				drt.sourceAlphaBlendFactor      = s_blendFactor[srcA][1];
 				drt.destinationAlphaBlendFactor = s_blendFactor[dstA][1];
 				drt.destinationAlphaBlendFactor = s_blendFactor[dstA][1];
-				drt.alphaBlendOperation			= s_blendEquation[equA];
+				drt.alphaBlendOperation         = s_blendEquation[equA];
 
 
 				drt.writeMask = writeMask;
 				drt.writeMask = writeMask;
 			}
 			}
@@ -1512,28 +1520,28 @@ namespace bgfx { namespace mtl
 			{
 			{
 				for (uint32_t ii = 1, rgba = _rgba; ii < frameBufferAttachment; ++ii, rgba >>= 11)
 				for (uint32_t ii = 1, rgba = _rgba; ii < frameBufferAttachment; ++ii, rgba >>= 11)
 				{
 				{
-					RenderPipelineColorAttachmentDescriptor drt = pipelineDesc.colorAttachments[ii];
+					RenderPipelineColorAttachmentDescriptor drt = pd.colorAttachments[ii];
 
 
 					drt.blendingEnabled = 0 != (rgba&0x7ff);
 					drt.blendingEnabled = 0 != (rgba&0x7ff);
 
 
-					const uint32_t src			 = (rgba   )&0xf;
-					const uint32_t dst			 = (rgba>>4)&0xf;
+					const uint32_t src           = (rgba   )&0xf;
+					const uint32_t dst           = (rgba>>4)&0xf;
 					const uint32_t equationIndex = (rgba>>8)&0x7;
 					const uint32_t equationIndex = (rgba>>8)&0x7;
 
 
-					drt.sourceRGBBlendFactor       = s_blendFactor[src][0];
-					drt.destinationRGBBlendFactor  = s_blendFactor[dst][0];
-					drt.rgbBlendOperation		   = s_blendEquation[equationIndex];
+					drt.sourceRGBBlendFactor      = s_blendFactor[src][0];
+					drt.destinationRGBBlendFactor = s_blendFactor[dst][0];
+					drt.rgbBlendOperation         = s_blendEquation[equationIndex];
 
 
-					drt.sourceAlphaBlendFactor		= s_blendFactor[src][1];
+					drt.sourceAlphaBlendFactor      = s_blendFactor[src][1];
 					drt.destinationAlphaBlendFactor = s_blendFactor[dst][1];
 					drt.destinationAlphaBlendFactor = s_blendFactor[dst][1];
-					drt.alphaBlendOperation			= s_blendEquation[equationIndex];
+					drt.alphaBlendOperation         = s_blendEquation[equationIndex];
 
 
 					drt.writeMask = writeMask;
 					drt.writeMask = writeMask;
 				}
 				}
 			}
 			}
 
 
-			pipelineDesc.vertexFunction = m_vsh->m_function;
-			pipelineDesc.fragmentFunction = m_fsh->m_function;
+			pd.vertexFunction = m_vsh->m_function;
+			pd.fragmentFunction = m_fsh->m_function;
 
 
 			if (isValid(_declHandle))
 			if (isValid(_declHandle))
 			{
 			{
@@ -1551,9 +1559,9 @@ namespace bgfx { namespace mtl
 					bool normalized;
 					bool normalized;
 					bool asInt;
 					bool asInt;
 					vertexDecl.decode(attr, num, type, normalized, asInt);
 					vertexDecl.decode(attr, num, type, normalized, asInt);
-					BX_CHECK(num<=4, "num must be <=4");
+					BX_CHECK(num <= 4, "num must be <=4");
 
 
-					if (0xff != vertexDecl.m_attributes[attr])
+					if (UINT16_MAX != vertexDecl.m_attributes[attr])
 					{
 					{
 						vertexDesc.attributes[loc].format = s_attribType[type][num-1][normalized?1:0];
 						vertexDesc.attributes[loc].format = s_attribType[type][num-1][normalized?1:0];
 						vertexDesc.attributes[loc].bufferIndex = 1;
 						vertexDesc.attributes[loc].bufferIndex = 1;
@@ -1576,7 +1584,7 @@ namespace bgfx { namespace mtl
 
 
 				if (_numInstanceData > 0)
 				if (_numInstanceData > 0)
 				{
 				{
-					for (uint32_t ii = 0; 0xffff != m_instanceData[ii]; ++ii)
+					for (uint32_t ii = 0; UINT16_MAX != m_instanceData[ii]; ++ii)
 					{
 					{
 						uint32_t loc = m_instanceData[ii];
 						uint32_t loc = m_instanceData[ii];
 						vertexDesc.attributes[loc].format = MTLVertexFormatFloat4;
 						vertexDesc.attributes[loc].format = MTLVertexFormatFloat4;
@@ -1589,37 +1597,38 @@ namespace bgfx { namespace mtl
 					vertexDesc.layouts[2].stepRate = 1;
 					vertexDesc.layouts[2].stepRate = 1;
 				}
 				}
 
 
-				pipelineDesc.vertexDescriptor = vertexDesc;
+				pd.vertexDescriptor = vertexDesc;
 			}
 			}
 
 
 			if (m_processedUniforms)
 			if (m_processedUniforms)
 			{
 			{
-				rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pipelineDesc);
+				rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pd);
 			}
 			}
 			else
 			else
 			{
 			{
 				m_numPredefined = 0;
 				m_numPredefined = 0;
 				RenderPipelineReflection reflection = NULL;
 				RenderPipelineReflection reflection = NULL;
-				rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pipelineDesc, MTLPipelineOptionBufferTypeInfo, &reflection);
+				rps = s_renderMtl->m_device.newRenderPipelineStateWithDescriptor(pd, MTLPipelineOptionBufferTypeInfo, &reflection);
 
 
-				if ( NULL != reflection )
+				if (NULL != reflection)
 				{
 				{
 					for (uint32_t shaderType = 0; shaderType < 2; ++shaderType)
 					for (uint32_t shaderType = 0; shaderType < 2; ++shaderType)
 					{
 					{
 						UniformBuffer*& constantBuffer = (shaderType == 0 ? m_vshConstantBuffer : m_fshConstantBuffer);
 						UniformBuffer*& constantBuffer = (shaderType == 0 ? m_vshConstantBuffer : m_fshConstantBuffer);
 						uint8_t fragmentBit = (1 == shaderType ? BGFX_UNIFORM_FRAGMENTBIT : 0);
 						uint8_t fragmentBit = (1 == shaderType ? BGFX_UNIFORM_FRAGMENTBIT : 0);
 
 
-						for( MTLArgument* arg in (shaderType == 0 ? reflection.vertexArguments : reflection.fragmentArguments))
+						for (MTLArgument* arg in (shaderType == 0 ? reflection.vertexArguments : reflection.fragmentArguments))
 						{
 						{
 							BX_TRACE("arg: %s type:%d", utf8String(arg.name), arg.type);
 							BX_TRACE("arg: %s type:%d", utf8String(arg.name), arg.type);
 							if (arg.active)
 							if (arg.active)
 							{
 							{
-								if (arg.type == MTLArgumentTypeBuffer && !strcmp(utf8String(arg.name),SHADER_UNIFORM_NAME) )
+								if (arg.type == MTLArgumentTypeBuffer
+								&& 0 == strcmp(utf8String(arg.name), SHADER_UNIFORM_NAME) )
 								{
 								{
 									BX_CHECK( arg.index == 0, "Uniform buffer must be in the buffer slot 0.");
 									BX_CHECK( arg.index == 0, "Uniform buffer must be in the buffer slot 0.");
 									BX_CHECK( MTLDataTypeStruct == arg.bufferDataType, "%s's type must be a struct",SHADER_UNIFORM_NAME );
 									BX_CHECK( MTLDataTypeStruct == arg.bufferDataType, "%s's type must be a struct",SHADER_UNIFORM_NAME );
 
 
-									if ( MTLDataTypeStruct == arg.bufferDataType )
+									if (MTLDataTypeStruct == arg.bufferDataType)
 									{
 									{
 										if (shaderType == 0)
 										if (shaderType == 0)
 										{
 										{
@@ -1632,7 +1641,7 @@ namespace bgfx { namespace mtl
 											m_fshConstantBufferAlignmentMask = (uint32_t)arg.bufferAlignment - 1;
 											m_fshConstantBufferAlignmentMask = (uint32_t)arg.bufferAlignment - 1;
 										}
 										}
 
 
-										for( MTLStructMember* uniform in arg.bufferStructType.members )
+										for (MTLStructMember* uniform in arg.bufferStructType.members )
 										{
 										{
 											const char* name = utf8String(uniform.name);
 											const char* name = utf8String(uniform.name);
 											BX_TRACE("uniform: %s type:%d", name, uniform.dataType);
 											BX_TRACE("uniform: %s type:%d", name, uniform.dataType);
@@ -1687,21 +1696,27 @@ namespace bgfx { namespace mtl
 
 
 										}
 										}
 									}
 									}
-								} else if (arg.type == MTLArgumentTypeTexture)
+								}
+								else if (arg.type == MTLArgumentTypeTexture)
 								{
 								{
 									const char* name = utf8String(arg.name);
 									const char* name = utf8String(arg.name);
 									BX_TRACE("texture: %s index:%d", name, arg.index);
 									BX_TRACE("texture: %s index:%d", name, arg.index);
-								} else if (arg.type == MTLArgumentTypeSampler)
+								}
+								else if (arg.type == MTLArgumentTypeSampler)
 								{
 								{
 									const char* name = utf8String(arg.name);
 									const char* name = utf8String(arg.name);
 									BX_TRACE("sampler: %s index:%d", name, arg.index);
 									BX_TRACE("sampler: %s index:%d", name, arg.index);
 								}
 								}
 							}
 							}
 						}
 						}
+
 						if (NULL != constantBuffer)
 						if (NULL != constantBuffer)
+						{
 							constantBuffer->finish();
 							constantBuffer->finish();
+						}
 					}
 					}
 				}
 				}
+
 				m_processedUniforms = true;
 				m_processedUniforms = true;
 			}
 			}
 
 
@@ -1829,11 +1844,15 @@ namespace bgfx { namespace mtl
 			desc.depth = bx::uint32_max(1,imageContainer.m_depth);
 			desc.depth = bx::uint32_max(1,imageContainer.m_depth);
 			desc.mipmapLevelCount = imageContainer.m_numMips;
 			desc.mipmapLevelCount = imageContainer.m_numMips;
 			desc.sampleCount = 1; //TODO: set samplecount -  If textureType is not MTLTextureType2DMultisample, the value must be 1.
 			desc.sampleCount = 1; //TODO: set samplecount -  If textureType is not MTLTextureType2DMultisample, the value must be 1.
+			desc.resourceOptions = MTLResourceStorageModePrivate;
+			desc.cpuCacheMode    = MTLCPUCacheModeDefaultCache;
+			desc.storageMode     = MTLStorageModePrivate;
 
 
 			//TODO: set resource flags depending on usage(renderTarget/computeWrite/etc) on iOS9/OSX
 			//TODO: set resource flags depending on usage(renderTarget/computeWrite/etc) on iOS9/OSX
 
 
 			m_ptr = s_renderMtl->m_device.newTextureWithDescriptor(desc);
 			m_ptr = s_renderMtl->m_device.newTextureWithDescriptor(desc);
-			if ( m_requestedFormat == TextureFormat::D24S8 && desc.pixelFormat == MTLPixelFormatDepth32Float )
+			if (m_requestedFormat == TextureFormat::D24S8
+			&&  desc.pixelFormat  == MTLPixelFormatDepth32Float)
 			{
 			{
 				desc.pixelFormat = MTLPixelFormatStencil8;
 				desc.pixelFormat = MTLPixelFormatStencil8;
 				m_ptrStencil = s_renderMtl->m_device.newTextureWithDescriptor(desc);
 				m_ptrStencil = s_renderMtl->m_device.newTextureWithDescriptor(desc);
@@ -1879,7 +1898,7 @@ namespace bgfx { namespace mtl
 						uint32_t bytesPerRow;
 						uint32_t bytesPerRow;
 						uint32_t bytesPerImage;
 						uint32_t bytesPerImage;
 
 
-						if ( compressed && !convert)
+						if (compressed && !convert)
 						{
 						{
 							if (format >= 160 /*MTLPixelFormatPVRTC_RGB_2BPP*/
 							if (format >= 160 /*MTLPixelFormatPVRTC_RGB_2BPP*/
 							&&  format <= 167 /*MTLPixelFormatPVRTC_RGBA_4BPP_sRGB*/)
 							&&  format <= 167 /*MTLPixelFormatPVRTC_RGBA_4BPP_sRGB*/)
@@ -2217,7 +2236,7 @@ namespace bgfx { namespace mtl
 
 
 					//TODO: optimize store actions use discard flag
 					//TODO: optimize store actions use discard flag
 					RenderPassDepthAttachmentDescriptor depthAttachment = renderPassDescriptor.depthAttachment;
 					RenderPassDepthAttachmentDescriptor depthAttachment = renderPassDescriptor.depthAttachment;
-					if ( NULL != depthAttachment.texture)
+					if (NULL != depthAttachment.texture)
 					{
 					{
 						depthAttachment.clearDepth = clr.m_depth;
 						depthAttachment.clearDepth = clr.m_depth;
 						depthAttachment.loadAction = (BGFX_CLEAR_DEPTH & clr.m_flags) ? MTLLoadActionClear : MTLLoadActionLoad;
 						depthAttachment.loadAction = (BGFX_CLEAR_DEPTH & clr.m_flags) ? MTLLoadActionClear : MTLLoadActionLoad;
@@ -2225,14 +2244,14 @@ namespace bgfx { namespace mtl
 					}
 					}
 
 
 					RenderPassStencilAttachmentDescriptor stencilAttachment = renderPassDescriptor.stencilAttachment;
 					RenderPassStencilAttachmentDescriptor stencilAttachment = renderPassDescriptor.stencilAttachment;
-					if ( NULL != stencilAttachment.texture )
+					if (NULL != stencilAttachment.texture)
 					{
 					{
 						stencilAttachment.clearStencil = clr.m_stencil;
 						stencilAttachment.clearStencil = clr.m_stencil;
-						stencilAttachment.loadAction = (BGFX_CLEAR_STENCIL & clr.m_flags) ? MTLLoadActionClear : MTLLoadActionLoad;
-						stencilAttachment.storeAction = MTLStoreActionStore;
+						stencilAttachment.loadAction   = (BGFX_CLEAR_STENCIL & clr.m_flags) ? MTLLoadActionClear : MTLLoadActionLoad;
+						stencilAttachment.storeAction  = MTLStoreActionStore;
 					}
 					}
 
 
-					if ( 0 != m_renderCommandEncoder)
+					if (0 != m_renderCommandEncoder)
 					{
 					{
 						m_renderCommandEncoder.endEncoding();
 						m_renderCommandEncoder.endEncoding();
 					}
 					}
@@ -2249,7 +2268,7 @@ namespace bgfx { namespace mtl
 
 
 					if (BX_ENABLED(BGFX_CONFIG_DEBUG_MTL) )
 					if (BX_ENABLED(BGFX_CONFIG_DEBUG_MTL) )
 					{
 					{
-						if ( item != 1) //ASK: better check ? I don't get the whole restart thing
+						if (item != 1) //ASK: better check ? I don't get the whole restart thing
 							rce.popDebugGroup();
 							rce.popDebugGroup();
 
 
 						rce.pushDebugGroup(s_viewName[view]);
 						rce.pushDebugGroup(s_viewName[view]);
@@ -2351,13 +2370,13 @@ namespace bgfx { namespace mtl
 					rce.setScissorRect(rc);
 					rce.setScissorRect(rc);
 				}
 				}
 
 
-				if ( (BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK) & changedFlags
+				if ((BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK) & changedFlags
 					|| 0 != changedStencil)
 					|| 0 != changedStencil)
 				{
 				{
 					setDepthStencilState(newFlags,newStencil);
 					setDepthStencilState(newFlags,newStencil);
 				}
 				}
 
 
-				if ( (0
+				if ((0
 					  | BGFX_STATE_CULL_MASK
 					  | BGFX_STATE_CULL_MASK
 					  | BGFX_STATE_ALPHA_REF_MASK
 					  | BGFX_STATE_ALPHA_REF_MASK
 					  | BGFX_STATE_PT_MASK
 					  | BGFX_STATE_PT_MASK
@@ -2385,7 +2404,7 @@ namespace bgfx { namespace mtl
 					}
 					}
 				}
 				}
 
 
-				if ( (blendFactor != draw.m_rgba) && !(newFlags & BGFX_STATE_BLEND_INDEPENDENT) )
+				if ((blendFactor != draw.m_rgba) && !(newFlags & BGFX_STATE_BLEND_INDEPENDENT) )
 				{
 				{
 					const uint32_t rgba = draw.m_rgba;
 					const uint32_t rgba = draw.m_rgba;
 					float rr = ( (rgba>>24)     )/255.0f;
 					float rr = ( (rgba>>24)     )/255.0f;
@@ -2428,7 +2447,7 @@ namespace bgfx { namespace mtl
 						decl.idx = !isValid(vb.m_decl) ? draw.m_vertexDecl.idx : vb.m_decl.idx;
 						decl.idx = !isValid(vb.m_decl) ? draw.m_vertexDecl.idx : vb.m_decl.idx;
 
 
 						RenderPipelineState pipelineState = program.getRenderPipelineState(newFlags, draw.m_rgba, fbh, decl, draw.m_instanceDataStride/16);
 						RenderPipelineState pipelineState = program.getRenderPipelineState(newFlags, draw.m_rgba, fbh, decl, draw.m_instanceDataStride/16);
-						if ( NULL == pipelineState )
+						if (NULL == pipelineState )
 						{  //call with invalid program
 						{  //call with invalid program
 							currentProgram = NULL;
 							currentProgram = NULL;
 							programIdx = invalidHandle;
 							programIdx = invalidHandle;
@@ -2449,14 +2468,14 @@ namespace bgfx { namespace mtl
 					uint32_t vertexUniformBufferSize = program.m_vshConstantBufferSize;
 					uint32_t vertexUniformBufferSize = program.m_vshConstantBufferSize;
 					uint32_t fragmentUniformBufferSize = program.m_fshConstantBufferSize;
 					uint32_t fragmentUniformBufferSize = program.m_fshConstantBufferSize;
 
 
-					if ( vertexUniformBufferSize )
+					if (vertexUniformBufferSize )
 					{
 					{
 						m_uniformBufferVertexOffset = BX_ALIGN_MASK(m_uniformBufferVertexOffset, program.m_vshConstantBufferAlignmentMask);
 						m_uniformBufferVertexOffset = BX_ALIGN_MASK(m_uniformBufferVertexOffset, program.m_vshConstantBufferAlignmentMask);
 						rce.setVertexBuffer(m_uniformBuffer, m_uniformBufferVertexOffset, 0);
 						rce.setVertexBuffer(m_uniformBuffer, m_uniformBufferVertexOffset, 0);
 					}
 					}
 
 
 					m_uniformBufferFragmentOffset = m_uniformBufferVertexOffset + vertexUniformBufferSize;
 					m_uniformBufferFragmentOffset = m_uniformBufferVertexOffset + vertexUniformBufferSize;
-					if ( fragmentUniformBufferSize )
+					if (fragmentUniformBufferSize )
 					{
 					{
 						m_uniformBufferFragmentOffset = BX_ALIGN_MASK(m_uniformBufferFragmentOffset, program.m_fshConstantBufferAlignmentMask);
 						m_uniformBufferFragmentOffset = BX_ALIGN_MASK(m_uniformBufferFragmentOffset, program.m_fshConstantBufferAlignmentMask);
 						rce.setFragmentBuffer(m_uniformBuffer, m_uniformBufferFragmentOffset, 0);
 						rce.setFragmentBuffer(m_uniformBuffer, m_uniformBufferFragmentOffset, 0);
@@ -2626,8 +2645,10 @@ namespace bgfx { namespace mtl
 
 
 		if (BX_ENABLED(BGFX_CONFIG_DEBUG_MTL) )
 		if (BX_ENABLED(BGFX_CONFIG_DEBUG_MTL) )
 		{
 		{
-			if ( 0 < _render->m_num)
+			if (0 < _render->m_num)
+			{
 				rce.popDebugGroup();
 				rce.popDebugGroup();
+			}
 		}
 		}
 
 
 		//TODO: debug stats
 		//TODO: debug stats