Merge branch 'master' of https://github.com/billhollings/MoltenVK into fastmath
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 7ee10cc..48cf717 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -20,7 +20,8 @@
- Advertise support for `shaderInt64` feature.
- Support fast math on MSL compiler via `MVKConfiguration::fastMathEnabled` configuration
- setting and `MVK_CONFIG_FAST_MATH_ENABLED` environment variable (both disabled by default).
+ setting and `MVK_CONFIG_FAST_MATH_ENABLED` environment variable (enabled by default).
+- Support compiling MSL with position invariance if indicated in SPIRV shader.
- `vkGetMoltenVKConfigurationMVK()` and `vkSetMoltenVKConfigurationMVK()` functions
can now be used with a `VkInstance` from another Vulkan layer, or with a `VK_NULL_HANDLE VkInstance`.
- `MVKConfiguration` extended to cover all MoltenVK environment variables.
diff --git a/ExternalRevisions/SPIRV-Cross_repo_revision b/ExternalRevisions/SPIRV-Cross_repo_revision
index e1ad29a..0e4d400 100644
--- a/ExternalRevisions/SPIRV-Cross_repo_revision
+++ b/ExternalRevisions/SPIRV-Cross_repo_revision
@@ -1 +1 @@
-9acb9ec31f5a8ef80ea6b994bb77be787b08d3d1
+4741bbaa641d118ca1864094decd1ba977316161
diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
index 6e69f10..1dc0503 100644
--- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
+++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
@@ -470,7 +470,7 @@
* The initial value or this parameter is set by the
* MVK_CONFIG_FAST_MATH_ENABLED
* runtime environment variable or MoltenVK compile-time build setting.
- * If neither is set, the value of this parameter defaults to false.
+ * If neither is set, the value of this parameter defaults to true.
*/
VkBool32 fastMathEnabled;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index e45d810..dab1c46 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -648,8 +648,14 @@
/** Returns the underlying Metal device. */
inline id<MTLDevice> getMTLDevice() { return _physicalDevice->getMTLDevice(); }
- /** Returns standard compilation options to be used when compiling MSL shaders. */
- inline MTLCompileOptions* getMTLCompileOptions() { return _mtlCompileOptions; }
+ /**
+ * Returns an autoreleased options object to be used when compiling MSL shaders.
+ * The useFastMath parameter is and-combined with MVKConfiguration::fastMathEnabled
+ * to determine whether to enable fast math optimizations in the compiled shader.
+ * The preserveInvariance parameter indicates that the shader requires the position
+ * output invariance across invocations (typically for the position output).
+ */
+ MTLCompileOptions* getMTLCompileOptions(bool useFastMath = true, bool preserveInvariance = false);
/** Returns the Metal vertex buffer index to use for the specified vertex attribute binding number. */
uint32_t getMetalBufferIndexForVertexAttributeBinding(uint32_t binding);
@@ -762,7 +768,6 @@
void initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo);
void initQueues(const VkDeviceCreateInfo* pCreateInfo);
void reservePrivateData(const VkDeviceCreateInfo* pCreateInfo);
- void initMTLCompileOptions();
void enableFeatures(const VkDeviceCreateInfo* pCreateInfo);
void enableFeatures(const VkBool32* pEnable, const VkBool32* pRequested, const VkBool32* pAvailable, uint32_t count);
void enableExtensions(const VkDeviceCreateInfo* pCreateInfo);
@@ -775,7 +780,6 @@
MVKPhysicalDevice* _physicalDevice;
MVKCommandResourceFactory* _commandResourceFactory;
- MTLCompileOptions* _mtlCompileOptions;
MVKSmallVector<MVKSmallVector<MVKQueue*, kMVKQueueCountPerQueueFamily>, kMVKQueueFamilyCount> _queuesByQueueFamilyIndex;
MVKSmallVector<MVKResource*, 256> _resources;
MVKSmallVector<MVKPrivateDataSlot*> _privateDataSlots;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 001dee6..4d49f92 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -3651,6 +3651,16 @@
return _defaultMTLSamplerState;
}
+MTLCompileOptions* MVKDevice::getMTLCompileOptions(bool useFastMath, bool preserveInvariance) {
+ MTLCompileOptions* mtlCompOpt = [MTLCompileOptions new];
+ mtlCompOpt.languageVersion = _pMetalFeatures->mslVersionEnum;
+ mtlCompOpt.fastMathEnabled = useFastMath && mvkGetMVKConfiguration()->fastMathEnabled;
+ if ([mtlCompOpt respondsToSelector: @selector(setPreserveInvariance:)]) {
+ [mtlCompOpt setPreserveInvariance: preserveInvariance];
+ }
+ return [mtlCompOpt autorelease];
+}
+
// Can't use prefilled Metal command buffers if any of the resource descriptors can be updated after binding.
bool MVKDevice::shouldPrefillMTLCommandBuffers() {
return (mvkGetMVKConfiguration()->prefillMetalCommandBuffers &&
@@ -3703,8 +3713,6 @@
_defaultMTLSamplerState = nil;
- initMTLCompileOptions(); // Before command resource factory
-
_commandResourceFactory = new MVKCommandResourceFactory(this);
// This code will be refactored in an upcoming release, but for now,
@@ -4085,19 +4093,12 @@
}
}
-void MVKDevice::initMTLCompileOptions() {
- _mtlCompileOptions = [MTLCompileOptions new]; // retained
- _mtlCompileOptions.languageVersion = _pMetalFeatures->mslVersionEnum;
- _mtlCompileOptions.fastMathEnabled = mvkGetMVKConfiguration()->fastMathEnabled;
-}
-
MVKDevice::~MVKDevice() {
for (auto& queues : _queuesByQueueFamilyIndex) {
mvkDestroyContainerContents(queues);
}
_commandResourceFactory->destroy();
- [_mtlCompileOptions release];
[_globalVisibilityResultMTLBuffer release];
[_defaultMTLSamplerState release];
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 027803c..932b26b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -2074,7 +2074,8 @@
archive(ep.mtlFunctionName,
ep.workgroupSize.width,
ep.workgroupSize.height,
- ep.workgroupSize.depth);
+ ep.workgroupSize.depth,
+ ep.supportsFastMath);
}
template<class Archive>
@@ -2113,6 +2114,7 @@
void serialize(Archive & archive, SPIRVToMSLConversionResults& scr) {
archive(scr.entryPoint,
scr.isRasterizationDisabled,
+ scr.isPositionInvariant,
scr.needsSwizzleBuffer,
scr.needsOutputBuffer,
scr.needsPatchOutputBuffer,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
index 49b0ce2..7b45d55 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.h
@@ -254,7 +254,8 @@
* If the Metal library compiler does not return within MVKConfiguration::metalCompileTimeout
* nanoseconds, an error will be generated and logged, and nil will be returned.
*/
- id<MTLLibrary> newMTLLibrary(NSString* mslSourceCode);
+ id<MTLLibrary> newMTLLibrary(NSString* mslSourceCode,
+ const SPIRVToMSLConversionResults& shaderConversionResults);
#pragma mark Construction
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
index e88bfdd..b30d924 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
@@ -135,8 +135,8 @@
const SPIRVToMSLConversionResults& shaderConversionResults) : _owner(owner) {
MVKShaderLibraryCompiler* slc = new MVKShaderLibraryCompiler(_owner);
- NSString* nsSrc = [[NSString alloc] initWithUTF8String: mslSourceCode.c_str()]; // temp retained
- _mtlLibrary = slc->newMTLLibrary(nsSrc); // retained
+ NSString* nsSrc = [[NSString alloc] initWithUTF8String: mslSourceCode.c_str()]; // temp retained
+ _mtlLibrary = slc->newMTLLibrary(nsSrc, shaderConversionResults); // retained
[nsSrc release]; // release temp string
slc->destroy();
@@ -415,12 +415,14 @@
#pragma mark -
#pragma mark MVKShaderLibraryCompiler
-id<MTLLibrary> MVKShaderLibraryCompiler::newMTLLibrary(NSString* mslSourceCode) {
+id<MTLLibrary> MVKShaderLibraryCompiler::newMTLLibrary(NSString* mslSourceCode,
+ const SPIRVToMSLConversionResults& shaderConversionResults) {
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
[_owner->getMTLDevice() newLibraryWithSource: mslSourceCode
- options: _owner->getDevice()->getMTLCompileOptions()
+ options: _owner->getDevice()->getMTLCompileOptions(shaderConversionResults.entryPoint.supportsFastMath,
+ shaderConversionResults.isPositionInvariant)
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
bool isLate = compileComplete(mtlLib, error);
if (isLate) { destroy(); }
diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
index 5eb6efe..1818903 100644
--- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
+++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h
@@ -173,9 +173,9 @@
# define MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE 0
#endif
-/** Set the fastMathEnabled Metal Compiler option. Disabled by default. */
+/** Set the fastMathEnabled Metal Compiler option. Enabled by default. */
#ifndef MVK_CONFIG_FAST_MATH_ENABLED
-# define MVK_CONFIG_FAST_MATH_ENABLED 0
+# define MVK_CONFIG_FAST_MATH_ENABLED 1
#endif
/**
diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp
index f57d623..996374a 100644
--- a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp
+++ b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.cpp
@@ -25,6 +25,7 @@
using namespace mvk;
using namespace std;
+using namespace spv;
using namespace SPIRV_CROSS_NAMESPACE;
@@ -144,9 +145,9 @@
}
MVK_PUBLIC_SYMBOL bool SPIRVToMSLConversionConfiguration::stageSupportsVertexAttributes() const {
- return (options.entryPointStage == spv::ExecutionModelVertex ||
- options.entryPointStage == spv::ExecutionModelTessellationControl ||
- options.entryPointStage == spv::ExecutionModelTessellationEvaluation);
+ return (options.entryPointStage == ExecutionModelVertex ||
+ options.entryPointStage == ExecutionModelTessellationControl ||
+ options.entryPointStage == ExecutionModelTessellationEvaluation);
}
// Check them all in case inactive VA's duplicate locations used by active VA's.
@@ -232,25 +233,25 @@
if (shouldLogSPIRV) { logSPIRV("Converting"); }
- SPIRV_CROSS_NAMESPACE::CompilerMSL* pMSLCompiler = nullptr;
+ CompilerMSL* pMSLCompiler = nullptr;
#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
try {
#endif
- pMSLCompiler = new SPIRV_CROSS_NAMESPACE::CompilerMSL(_spirv);
+ pMSLCompiler = new CompilerMSL(_spirv);
if (context.options.hasEntryPoint()) {
pMSLCompiler->set_entry_point(context.options.entryPointName, context.options.entryPointStage);
}
// Set up tessellation parameters if needed.
- if (context.options.entryPointStage == spv::ExecutionModelTessellationControl ||
- context.options.entryPointStage == spv::ExecutionModelTessellationEvaluation) {
- if (context.options.tessPatchKind != spv::ExecutionModeMax) {
+ if (context.options.entryPointStage == ExecutionModelTessellationControl ||
+ context.options.entryPointStage == ExecutionModelTessellationEvaluation) {
+ if (context.options.tessPatchKind != ExecutionModeMax) {
pMSLCompiler->set_execution_mode(context.options.tessPatchKind);
}
if (context.options.numTessControlPoints != 0) {
- pMSLCompiler->set_execution_mode(spv::ExecutionModeOutputVertices, context.options.numTessControlPoints);
+ pMSLCompiler->set_execution_mode(ExecutionModeOutputVertices, context.options.numTessControlPoints);
}
}
@@ -282,7 +283,7 @@
if (shouldLogMSL) { logSource(_msl, "MSL", "Converted"); }
#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
- } catch (SPIRV_CROSS_NAMESPACE::CompilerError& ex) {
+ } catch (CompilerError& ex) {
string errMsg("MSL conversion error: ");
errMsg += ex.what();
logError(errMsg.data());
@@ -297,6 +298,7 @@
// and mark which vertex attributes and resource bindings are used by the shader
populateEntryPoint(pMSLCompiler, context.options);
_shaderConversionResults.isRasterizationDisabled = pMSLCompiler && pMSLCompiler->get_is_rasterization_disabled();
+ _shaderConversionResults.isPositionInvariant = pMSLCompiler && pMSLCompiler->is_position_invariant();
_shaderConversionResults.needsSwizzleBuffer = pMSLCompiler && pMSLCompiler->needs_swizzle_buffer();
_shaderConversionResults.needsOutputBuffer = pMSLCompiler && pMSLCompiler->needs_output_buffer();
_shaderConversionResults.needsPatchOutputBuffer = pMSLCompiler && pMSLCompiler->needs_patch_output_buffer();
@@ -318,12 +320,12 @@
// To check GLSL conversion
if (shouldLogGLSL) {
- SPIRV_CROSS_NAMESPACE::CompilerGLSL* pGLSLCompiler = nullptr;
+ CompilerGLSL* pGLSLCompiler = nullptr;
#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
try {
#endif
- pGLSLCompiler = new SPIRV_CROSS_NAMESPACE::CompilerGLSL(_spirv);
+ pGLSLCompiler = new CompilerGLSL(_spirv);
auto options = pGLSLCompiler->get_common_options();
options.vulkan_semantics = true;
options.separate_shader_objects = true;
@@ -331,7 +333,7 @@
string glsl = pGLSLCompiler->compile();
logSource(glsl, "GLSL", "Estimated original");
#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
- } catch (SPIRV_CROSS_NAMESPACE::CompilerError& ex) {
+ } catch (CompilerError& ex) {
string errMsg("Original GLSL extraction error: ");
errMsg += ex.what();
logMsg(errMsg.data());
@@ -397,7 +399,7 @@
// Validates that the SPIR-V code will disassemble during logging.
bool SPIRVToMSLConverter::validateSPIRV() {
if (_spirv.size() < 5) { return false; }
- if (_spirv[0] != spv::MagicNumber) { return false; }
+ if (_spirv[0] != MagicNumber) { return false; }
if (_spirv[4] != 0) { return false; }
return true;
}
@@ -416,19 +418,19 @@
void SPIRVToMSLConverter::populateWorkgroupDimension(SPIRVWorkgroupSizeDimension& wgDim,
uint32_t size,
- SPIRV_CROSS_NAMESPACE::SpecializationConstant& spvSpecConst) {
+ SpecializationConstant& spvSpecConst) {
wgDim.size = max(size, 1u);
wgDim.isSpecialized = (uint32_t(spvSpecConst.id) != 0);
wgDim.specializationID = spvSpecConst.constant_id;
}
// Populates the entry point with info extracted from the SPRI-V compiler.
-void SPIRVToMSLConverter::populateEntryPoint(SPIRV_CROSS_NAMESPACE::Compiler* pCompiler,
+void SPIRVToMSLConverter::populateEntryPoint(Compiler* pCompiler,
SPIRVToMSLConversionOptions& options) {
if ( !pCompiler ) { return; }
- SPIRV_CROSS_NAMESPACE::SPIREntryPoint spvEP;
+ SPIREntryPoint spvEP;
if (options.hasEntryPoint()) {
spvEP = pCompiler->get_entry_point(options.entryPointName, options.entryPointStage);
} else {
@@ -441,8 +443,9 @@
auto& ep = _shaderConversionResults.entryPoint;
ep.mtlFunctionName = spvEP.name;
+ ep.supportsFastMath = !spvEP.flags.get(ExecutionModeSignedZeroInfNanPreserve);
- SPIRV_CROSS_NAMESPACE::SpecializationConstant widthSC, heightSC, depthSC;
+ SpecializationConstant widthSC, heightSC, depthSC;
pCompiler->get_work_group_size_specialization_constants(widthSC, heightSC, depthSC);
auto& wgSize = ep.workgroupSize;
diff --git a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h
index c35face..d1d127b 100644
--- a/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h
+++ b/MoltenVKShaderConverter/MoltenVKShaderConverter/SPIRVToMSLConverter.h
@@ -192,6 +192,7 @@
SPIRVWorkgroupSizeDimension height;
SPIRVWorkgroupSizeDimension depth;
} workgroupSize;
+ bool supportsFastMath = true;
} SPIRVEntryPoint;
/**
@@ -203,6 +204,7 @@
typedef struct SPIRVToMSLConversionResults {
SPIRVEntryPoint entryPoint;
bool isRasterizationDisabled = false;
+ bool isPositionInvariant = false;
bool needsSwizzleBuffer = false;
bool needsOutputBuffer = false;
bool needsPatchOutputBuffer = false;