For shaders created directly from MSL, set function name from
VkPipelineShaderStageCreateInfo::pName.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index e7f548f..22434c4 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -18,6 +18,8 @@
 
 Released TBD
 
+- For shaders created directly from MSL, set function name from 
+  `VkPipelineShaderStageCreateInfo::pName`.
 - On iOS GPU family 2 and earlier, support immutable depth-compare samplers 
   as constexpr samplers hardcoded in MSL.
 - Add `MTLCommandBuffer` completion timing performance tracking option.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
index 01dedda..ff54bfb 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
@@ -56,7 +56,22 @@
 	/** Returns the Vulkan API opaque object controlling this object. */
 	MVKVulkanAPIObject* getVulkanAPIObject() override { return _owner->getVulkanAPIObject(); };
 
-    /** Sets the number of threads in a single compute kernel workgroup, per dimension. */
+	/**
+	 * Sets the entry point function name.
+	 *
+	 * This is usually set automatically during shader conversion from SPIR-V to MSL.
+	 * For a library that was created directly from MSL, this function can be used to
+	 * set the name of the function if it has a different name than the default main0().
+	 */
+	void setEntryPointName(std::string& funcName);
+
+    /**
+	 * Sets the number of threads in a single compute kernel workgroup, per dimension.
+	 *
+	 * This is usually set automatically during shader conversion from SPIR-V to MSL.
+	 * For a library that was created directly from MSL, this function can be used to
+	 * set the workgroup size..
+	 */
     void setWorkgroupSize(uint32_t x, uint32_t y, uint32_t z);
     
 	/** Constructs an instance from the specified MSL source code. */
@@ -207,7 +222,7 @@
 	MVKShaderLibraryCache _shaderLibraryCache;
 	SPIRVToMSLConverter _spvConverter;
 	GLSLToSPIRVConverter _glslConverter;
-	MVKShaderLibrary* _defaultLibrary;
+	MVKShaderLibrary* _directMSLLibrary;
 	MVKShaderModuleKey _key;
     std::mutex _accessLock;
 };
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
index 6c7adb5..b80362b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
@@ -109,6 +109,17 @@
     return nil;
 }
 
+void MVKShaderLibrary::setEntryPointName(string& funcName) {
+	_shaderConversionResults.entryPoint.mtlFunctionName = funcName;
+}
+
+void MVKShaderLibrary::setWorkgroupSize(uint32_t x, uint32_t y, uint32_t z) {
+	auto& wgSize = _shaderConversionResults.entryPoint.workgroupSize;
+	wgSize.width.size = x;
+	wgSize.height.size = y;
+	wgSize.depth.size = z;
+}
+
 MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
 								   const string& mslSourceCode,
 								   const SPIRVToMSLConversionResults& shaderConversionResults) : _owner(owner) {
@@ -160,13 +171,6 @@
     }
 }
 
-void MVKShaderLibrary::setWorkgroupSize(uint32_t x, uint32_t y, uint32_t z) {
-	auto& wgSize = _shaderConversionResults.entryPoint.workgroupSize;
-    wgSize.width.size = x;
-    wgSize.height.size = y;
-    wgSize.depth.size = z;
-}
-
 MVKShaderLibrary::~MVKShaderLibrary() {
 	[_mtlLibrary release];
 }
@@ -236,7 +240,7 @@
 											   MVKPipelineCache* pipelineCache) {
 	lock_guard<mutex> lock(_accessLock);
 	
-	MVKShaderLibrary* mvkLib = _defaultLibrary;
+	MVKShaderLibrary* mvkLib = _directMSLLibrary;
 	if ( !mvkLib ) {
 		uint64_t startTime = _device->getPerformanceTimestamp();
 		if (pipelineCache) {
@@ -246,6 +250,7 @@
 		}
 		_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.shaderLibraryFromCache, startTime);
 	} else {
+		mvkLib->setEntryPointName(pContext->options.entryPointName);
 		pContext->markAllAttributesAndResourcesUsed();
 	}
 
@@ -302,12 +307,18 @@
 	}
 }
 
+void MVKShaderModule::setWorkgroupSize(uint32_t x, uint32_t y, uint32_t z) {
+	_spvConverter.setWorkgroupSize(x, y, z);
+	if(_directMSLLibrary) { _directMSLLibrary->setWorkgroupSize(x, y, z); }
+}
+
+
 #pragma mark Construction
 
 MVKShaderModule::MVKShaderModule(MVKDevice* device,
 								 const VkShaderModuleCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device), _shaderLibraryCache(this) {
 
-	_defaultLibrary = nullptr;
+	_directMSLLibrary = nullptr;
 
 	size_t codeSize = pCreateInfo->codeSize;
 
@@ -344,7 +355,7 @@
 			_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
 
 			_spvConverter.setMSL(pMSLCode, nullptr);
-			_defaultLibrary = new MVKShaderLibrary(this, _spvConverter.getMSL().c_str(), _spvConverter.getConversionResults());
+			_directMSLLibrary = new MVKShaderLibrary(this, _spvConverter.getMSL().c_str(), _spvConverter.getConversionResults());
 
 			break;
 		}
@@ -358,7 +369,7 @@
 			codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
 			_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
 
-			_defaultLibrary = new MVKShaderLibrary(this, (void*)(pMSLCode), mslCodeLen);
+			_directMSLLibrary = new MVKShaderLibrary(this, (void*)(pMSLCode), mslCodeLen);
 
 			break;
 		}
@@ -382,12 +393,7 @@
 }
 
 MVKShaderModule::~MVKShaderModule() {
-	if (_defaultLibrary) { _defaultLibrary->destroy(); }
-}
-
-void MVKShaderModule::setWorkgroupSize(uint32_t x, uint32_t y, uint32_t z) {
-    _spvConverter.setWorkgroupSize(x, y, z);
-    if(_defaultLibrary) { _defaultLibrary->setWorkgroupSize(x, y, z); }
+	if (_directMSLLibrary) { _directMSLLibrary->destroy(); }
 }