Enable MSL ffast-math compilation option by default.

Support querying SignedZeroInfNanPreserve execution mode
from SPIR-V to disable fast-math for individual shaders.
Clean up namespace references in SPIRVToMSLConverter.cpp.
This commit is contained in:
Bill Hollings 2021-01-28 08:05:33 -05:00
parent 2780ba1e40
commit 2343c0267b
10 changed files with 47 additions and 41 deletions

View File

@ -20,7 +20,7 @@ Released TBD
- 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).
- `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.

View File

@ -470,7 +470,7 @@ typedef struct {
* 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;

View File

@ -648,8 +648,12 @@ public:
/** 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 parameteris and-combined with MVKConfiguration::fastMathEnabled
* to determine whether to enable fast math optimizations in the compiled shader.
*/
MTLCompileOptions* getMTLCompileOptions(bool useFastMath = true);
/** Returns the Metal vertex buffer index to use for the specified vertex attribute binding number. */
uint32_t getMetalBufferIndexForVertexAttributeBinding(uint32_t binding);
@ -762,7 +766,6 @@ protected:
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 +778,6 @@ protected:
MVKPhysicalDevice* _physicalDevice;
MVKCommandResourceFactory* _commandResourceFactory;
MTLCompileOptions* _mtlCompileOptions;
MVKSmallVector<MVKSmallVector<MVKQueue*, kMVKQueueCountPerQueueFamily>, kMVKQueueFamilyCount> _queuesByQueueFamilyIndex;
MVKSmallVector<MVKResource*, 256> _resources;
MVKSmallVector<MVKPrivateDataSlot*> _privateDataSlots;

View File

@ -3639,6 +3639,13 @@ id<MTLSamplerState> MVKDevice::getDefaultMTLSamplerState() {
return _defaultMTLSamplerState;
}
MTLCompileOptions* MVKDevice::getMTLCompileOptions(bool useFastMath) {
MTLCompileOptions* mtlCompOpt = [MTLCompileOptions new];
mtlCompOpt.languageVersion = _pMetalFeatures->mslVersionEnum;
mtlCompOpt.fastMathEnabled = useFastMath && mvkGetMVKConfiguration()->fastMathEnabled;
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 &&
@ -3691,8 +3698,6 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
_defaultMTLSamplerState = nil;
initMTLCompileOptions(); // Before command resource factory
_commandResourceFactory = new MVKCommandResourceFactory(this);
// This code will be refactored in an upcoming release, but for now,
@ -4073,19 +4078,12 @@ void MVKDevice::reservePrivateData(const VkDeviceCreateInfo* pCreateInfo) {
}
}
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];

View File

@ -2074,7 +2074,8 @@ namespace mvk {
archive(ep.mtlFunctionName,
ep.workgroupSize.width,
ep.workgroupSize.height,
ep.workgroupSize.depth);
ep.workgroupSize.depth,
ep.supportsFastMath);
}
template<class Archive>

View File

@ -254,7 +254,7 @@ public:
* 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, bool useFastMath);
#pragma mark Construction

View File

@ -135,8 +135,8 @@ MVKShaderLibrary::MVKShaderLibrary(MVKVulkanAPIDeviceObject* owner,
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.entryPoint.supportsFastMath); // retained
[nsSrc release]; // release temp string
slc->destroy();
@ -415,12 +415,12 @@ MVKShaderModule::~MVKShaderModule() {
#pragma mark -
#pragma mark MVKShaderLibraryCompiler
id<MTLLibrary> MVKShaderLibraryCompiler::newMTLLibrary(NSString* mslSourceCode) {
id<MTLLibrary> MVKShaderLibraryCompiler::newMTLLibrary(NSString* mslSourceCode, bool useFastMath) {
unique_lock<mutex> lock(_completionLock);
compile(lock, ^{
[_owner->getMTLDevice() newLibraryWithSource: mslSourceCode
options: _owner->getDevice()->getMTLCompileOptions()
options: _owner->getDevice()->getMTLCompileOptions(useFastMath)
completionHandler: ^(id<MTLLibrary> mtlLib, NSError* error) {
bool isLate = compileComplete(mtlLib, error);
if (isLate) { destroy(); }

View File

@ -173,9 +173,9 @@ void mvkSetMVKConfiguration(MVKConfiguration* pMVKConfig);
# 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
/**

View File

@ -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 mvk::MSLResourceBinding::matches(const MSLResourceBinding
}
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 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur
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 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur
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());
@ -305,6 +306,8 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur
_shaderConversionResults.needsDispatchBaseBuffer = pMSLCompiler && pMSLCompiler->needs_dispatch_base_buffer();
_shaderConversionResults.needsViewRangeBuffer = pMSLCompiler && pMSLCompiler->needs_view_mask_buffer();
for (auto& ctxSI : context.shaderInputs) {
ctxSI.isUsedByShader = pMSLCompiler->is_msl_shader_input_used(ctxSI.shaderInput.location);
}
@ -318,12 +321,12 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur
// 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 +334,7 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConversionConfigur
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 +400,7 @@ void SPIRVToMSLConverter::writeSPIRVToFile(string spvFilepath) {
// 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 +419,19 @@ void SPIRVToMSLConverter::logSource(string& src, const char* srcLang, const char
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 +444,9 @@ void SPIRVToMSLConverter::populateEntryPoint(SPIRV_CROSS_NAMESPACE::Compiler* pC
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;

View File

@ -192,6 +192,7 @@ namespace mvk {
SPIRVWorkgroupSizeDimension height;
SPIRVWorkgroupSizeDimension depth;
} workgroupSize;
bool supportsFastMath = true;
} SPIRVEntryPoint;
/**