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:
parent
2780ba1e40
commit
2343c0267b
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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(); }
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -192,6 +192,7 @@ namespace mvk {
|
||||
SPIRVWorkgroupSizeDimension height;
|
||||
SPIRVWorkgroupSizeDimension depth;
|
||||
} workgroupSize;
|
||||
bool supportsFastMath = true;
|
||||
} SPIRVEntryPoint;
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user