Merge pull request #200 from billhollings/master

Report correct workgroup sizes from MTLDevice.
diff --git a/MoltenVK/MoltenVK/API/mvk_datatypes.h b/MoltenVK/MoltenVK/API/mvk_datatypes.h
index 1bdb261..0be95ce 100644
--- a/MoltenVK/MoltenVK/API/mvk_datatypes.h
+++ b/MoltenVK/MoltenVK/API/mvk_datatypes.h
@@ -383,16 +383,26 @@
 	return vkExt;
 }
 
-/** Returns a Metal MTLOrigin constructed from the specified VkOffset3D. */
+/** Returns a Metal MTLOrigin constructed from a VkOffset3D. */
 static inline MTLOrigin mvkMTLOriginFromVkOffset3D(VkOffset3D vkOffset) {
 	return MTLOriginMake(vkOffset.x, vkOffset.y, vkOffset.z);
 }
 
-/** Returns a Metal MTLSize constructed from the specified VkExtent3D. */
+/** Returns a Vulkan VkOffset3D constructed from a Metal MTLOrigin. */
+static inline VkOffset3D mvkVkOffset3DFromMTLSize(MTLOrigin mtlOrigin) {
+	return { (int32_t)mtlOrigin.x, (int32_t)mtlOrigin.y, (int32_t)mtlOrigin.z };
+}
+
+/** Returns a Metal MTLSize constructed from a VkExtent3D. */
 static inline MTLSize mvkMTLSizeFromVkExtent3D(VkExtent3D vkExtent) {
 	return MTLSizeMake(vkExtent.width, vkExtent.height, vkExtent.depth);
 }
 
+/** Returns a Vulkan VkExtent3D  constructed from a Metal MTLSize. */
+static inline VkExtent3D mvkVkExtent3DFromMTLSize(MTLSize mtlSize) {
+	return { (uint32_t)mtlSize.width, (uint32_t)mtlSize.height, (uint32_t)mtlSize.depth };
+}
+
 
 #pragma mark -
 #pragma mark Memory options
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index ea04206..606cf8c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -35,6 +35,7 @@
 #include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
 #include "mvk_datatypes.h"
 #include "vk_mvk_moltenvk.h"
+
 #import "CAMetalLayer+MoltenVK.h"
 
 using namespace std;
@@ -590,7 +591,6 @@
     _properties.limits.optimalBufferCopyOffsetAlignment = 256;
 #endif
 
-
     _properties.limits.maxVertexOutputComponents = _properties.limits.maxFragmentInputComponents;
 
     _properties.limits.optimalBufferCopyRowPitchAlignment = 1;
@@ -605,30 +605,31 @@
     _properties.limits.lineWidthRange[1] = 1;
     _properties.limits.pointSizeGranularity = 1;
 
-#if MVK_IOS
-    if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily4_v1]) {
-        _properties.limits.maxComputeSharedMemorySize = (32 * KIBI);
-        _properties.limits.maxComputeWorkGroupInvocations = (1 * KIBI);
-    } else if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) {
-        _properties.limits.maxComputeSharedMemorySize = (16 * KIBI);
-        _properties.limits.maxComputeWorkGroupInvocations = 512;
-    } else {
-        _properties.limits.maxComputeSharedMemorySize = ((16 * KIBI) - 32);
-        _properties.limits.maxComputeWorkGroupInvocations = 512;
-    }
-#endif
-#if MVK_MACOS
-    _properties.limits.maxComputeSharedMemorySize = (32 * KIBI);
-    _properties.limits.maxComputeWorkGroupInvocations = (1 * KIBI);
-#endif
-
     _properties.limits.standardSampleLocations = VK_FALSE;
     _properties.limits.strictLines = VK_FALSE;
 
-	_properties.limits.maxComputeWorkGroupSize[0] = _properties.limits.maxComputeWorkGroupInvocations;
-	_properties.limits.maxComputeWorkGroupSize[1] = _properties.limits.maxComputeWorkGroupInvocations;
-	_properties.limits.maxComputeWorkGroupSize[2] = _properties.limits.maxComputeWorkGroupInvocations;
+	VkExtent3D wgSize = mvkVkExtent3DFromMTLSize(_mtlDevice.maxThreadsPerThreadgroup);
+	_properties.limits.maxComputeWorkGroupSize[0] = wgSize.width;
+	_properties.limits.maxComputeWorkGroupSize[1] = wgSize.height;
+	_properties.limits.maxComputeWorkGroupSize[2] = wgSize.depth;
+	_properties.limits.maxComputeWorkGroupInvocations = max({wgSize.width, wgSize.height, wgSize.depth});
 
+	if ( [_mtlDevice respondsToSelector: @selector(maxThreadgroupMemoryLength)] ) {
+		_properties.limits.maxComputeSharedMemorySize = (uint32_t)_mtlDevice.maxThreadgroupMemoryLength;
+	} else {
+#if MVK_IOS
+		if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily4_v1]) {
+			_properties.limits.maxComputeSharedMemorySize = (32 * KIBI);
+		} else if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) {
+			_properties.limits.maxComputeSharedMemorySize = (16 * KIBI);
+		} else {
+			_properties.limits.maxComputeSharedMemorySize = ((16 * KIBI) - 32);
+		}
+#endif
+#if MVK_MACOS
+		_properties.limits.maxComputeSharedMemorySize = (32 * KIBI);
+#endif
+	}
 
     // Features with no specific limits - default to unlimited int values
 
diff --git a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m
index 6c95818..726128f 100644
--- a/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m
+++ b/MoltenVK/MoltenVK/OS/CAMetalLayer+MoltenVK.m
@@ -39,14 +39,14 @@
 
 -(BOOL) displaySyncEnabledMVK {
 #if MVK_MACOS
-    if ( [self respondsToSelector: @selector(displaySyncEnabled)]) { return self.displaySyncEnabled; }
+    if ( [self respondsToSelector: @selector(displaySyncEnabled)] ) { return self.displaySyncEnabled; }
 #endif
     return YES;
 }
 
 -(void) setDisplaySyncEnabledMVK: (BOOL) enabled {
 #if MVK_MACOS
-    if ( [self respondsToSelector: @selector(setDisplaySyncEnabled:)]) { self.displaySyncEnabled = enabled; }
+    if ( [self respondsToSelector: @selector(setDisplaySyncEnabled:)] ) { self.displaySyncEnabled = enabled; }
 #endif
 }
 
diff --git a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m
index 8e9909b..87c6ea0 100644
--- a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m
+++ b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m
@@ -22,12 +22,12 @@
 @implementation MTLSamplerDescriptor (MoltenVK)
 
 -(MTLCompareFunction) compareFunctionMVK {
-	if ( [self respondsToSelector: @selector(compareFunction)]) { return self.compareFunction; }
+	if ( [self respondsToSelector: @selector(compareFunction)] ) { return self.compareFunction; }
 	return MTLCompareFunctionNever;
 }
 
 -(void) setCompareFunctionMVK: (MTLCompareFunction) cmpFunc {
-	if ( [self respondsToSelector: @selector(setCompareFunction:)]) { self.compareFunction = cmpFunc; }
+	if ( [self respondsToSelector: @selector(setCompareFunction:)] ) { self.compareFunction = cmpFunc; }
 }
 
 @end
diff --git a/MoltenVK/MoltenVK/OS/MTLTextureDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLTextureDescriptor+MoltenVK.m
index 1439e0d..b653dde 100644
--- a/MoltenVK/MoltenVK/OS/MTLTextureDescriptor+MoltenVK.m
+++ b/MoltenVK/MoltenVK/OS/MTLTextureDescriptor+MoltenVK.m
@@ -22,21 +22,21 @@
 @implementation MTLTextureDescriptor (MoltenVK)
 
 -(MTLTextureUsage) usageMVK {
-	if ( [self respondsToSelector: @selector(usage)]) { return self.usage; }
+	if ( [self respondsToSelector: @selector(usage)] ) { return self.usage; }
 	return MTLTextureUsageUnknown;
 }
 
 -(void) setUsageMVK: (MTLTextureUsage) usage {
-	if ( [self respondsToSelector: @selector(setUsage:)]) { self.usage = usage; }
+	if ( [self respondsToSelector: @selector(setUsage:)] ) { self.usage = usage; }
 }
 
 -(MTLStorageMode) storageModeMVK {
-	if ( [self respondsToSelector: @selector(storageMode)]) { return self.storageMode; }
+	if ( [self respondsToSelector: @selector(storageMode)] ) { return self.storageMode; }
 	return MTLStorageModeShared;
 }
 
 -(void) setStorageModeMVK: (MTLStorageMode) storageMode {
-	if ( [self respondsToSelector: @selector(setStorageMode:)]) { self.storageMode = storageMode; }
+	if ( [self respondsToSelector: @selector(setStorageMode:)] ) { self.storageMode = storageMode; }
 }
 
 @end