Add support for the VK_NV_glsl_shader extension.

Support runtime shader compilation from GLSL.
Return VK_ERROR_INVALID_SHADER_NV on shader and pipeline compilation errors.
Add MVKShaderCompilationPerformance::glslToSPRIV to track GLSL conversion performance.
Rename MoltenVKGLSLToSPIRVConverter MVKShaderStage enum to MVKGLSLConversionShaderStage
to avoid naming conflicts with MoltenVK MVKShaderStage enum.
Hologram demo load SPIR-V directly instead of using GLSL through either
MoltenVKGLSLToSPIRVConverter or VK_NV_glsl_shader extension.
Update to latest version of VulkanSamples that supports MVKGLSLConversionShaderStage.
This commit is contained in:
Bill Hollings 2019-05-10 12:21:03 -04:00
parent f79ccdfd94
commit c3aaf976ae
19 changed files with 197 additions and 160 deletions

View File

@ -9,12 +9,6 @@
/* Begin PBXBuildFile section */
A99789AF1CD3D4E2005E7DAC /* Hologram.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A99789831CD3D4E2005E7DAC /* Hologram.cpp */; };
A99789B01CD3D4E2005E7DAC /* Hologram.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A99789831CD3D4E2005E7DAC /* Hologram.cpp */; };
A99789B11CD3D4E2005E7DAC /* Hologram.frag in Resources */ = {isa = PBXBuildFile; fileRef = A99789841CD3D4E2005E7DAC /* Hologram.frag */; };
A99789B21CD3D4E2005E7DAC /* Hologram.frag in Resources */ = {isa = PBXBuildFile; fileRef = A99789841CD3D4E2005E7DAC /* Hologram.frag */; };
A99789B31CD3D4E2005E7DAC /* Hologram.push_constant.vert in Resources */ = {isa = PBXBuildFile; fileRef = A99789861CD3D4E2005E7DAC /* Hologram.push_constant.vert */; };
A99789B41CD3D4E2005E7DAC /* Hologram.push_constant.vert in Resources */ = {isa = PBXBuildFile; fileRef = A99789861CD3D4E2005E7DAC /* Hologram.push_constant.vert */; };
A99789B51CD3D4E2005E7DAC /* Hologram.vert in Resources */ = {isa = PBXBuildFile; fileRef = A99789871CD3D4E2005E7DAC /* Hologram.vert */; };
A99789B61CD3D4E2005E7DAC /* Hologram.vert in Resources */ = {isa = PBXBuildFile; fileRef = A99789871CD3D4E2005E7DAC /* Hologram.vert */; };
A99789B71CD3D4E2005E7DAC /* Main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A99789881CD3D4E2005E7DAC /* Main.cpp */; };
A99789B81CD3D4E2005E7DAC /* Main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A99789881CD3D4E2005E7DAC /* Main.cpp */; };
A99789B91CD3D4E2005E7DAC /* Meshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A99789891CD3D4E2005E7DAC /* Meshes.cpp */; };
@ -38,8 +32,6 @@
A9B67B901C3AAEA200373FFD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B8A1C3AAEA200373FFD /* Main.storyboard */; };
A9B67B911C3AAEA200373FFD /* macOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A9B67B8B1C3AAEA200373FFD /* macOS.xcassets */; };
A9C2AB99218503A400DDBC03 /* libMoltenVK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A9C2AB97218503A400DDBC03 /* libMoltenVK.a */; };
A9C2AB9A218503A400DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9C2AB98218503A400DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework */; };
A9C2AB9D218503BA00DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9C2AB9B218503BA00DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework */; };
A9C2AB9E218503BA00DDBC03 /* libMoltenVK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A9C2AB9C218503BA00DDBC03 /* libMoltenVK.a */; };
A9D516F81CD575E300097D96 /* HelpersDispatchTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9D516F61CD575E300097D96 /* HelpersDispatchTable.cpp */; };
A9D516F91CD575E300097D96 /* HelpersDispatchTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9D516F61CD575E300097D96 /* HelpersDispatchTable.cpp */; };
@ -47,16 +39,16 @@
/* Begin PBXFileReference section */
1D6058910D05DD3D006BFB54 /* Hologram.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Hologram.app; sourceTree = BUILT_PRODUCTS_DIR; };
A93374642284CD260059D36E /* Hologram.vert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hologram.vert.h; path = android/src/main/jni/Hologram.vert.h; sourceTree = "<group>"; };
A93374652284CD260059D36E /* Hologram.push_constant.vert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hologram.push_constant.vert.h; path = android/src/main/jni/Hologram.push_constant.vert.h; sourceTree = "<group>"; };
A93374662284CD260059D36E /* Hologram.frag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Hologram.frag.h; path = android/src/main/jni/Hologram.frag.h; sourceTree = "<group>"; };
A93CC3701CD56B8F00EB8A56 /* generate-dispatch-table */ = {isa = PBXFileReference; explicitFileType = text.script.python; path = "generate-dispatch-table"; sourceTree = "<group>"; };
A93CC3711CD56FD600EB8A56 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
A977BCFE1B66BB010067E5BF /* Hologram.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Hologram.app; sourceTree = BUILT_PRODUCTS_DIR; };
A997897F1CD3D4E2005E7DAC /* Game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Game.h; sourceTree = "<group>"; };
A99789821CD3D4E2005E7DAC /* Helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Helpers.h; sourceTree = "<group>"; };
A99789831CD3D4E2005E7DAC /* Hologram.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Hologram.cpp; sourceTree = "<group>"; };
A99789841CD3D4E2005E7DAC /* Hologram.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = Hologram.frag; sourceTree = "<group>"; };
A99789851CD3D4E2005E7DAC /* Hologram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Hologram.h; sourceTree = "<group>"; };
A99789861CD3D4E2005E7DAC /* Hologram.push_constant.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = Hologram.push_constant.vert; sourceTree = "<group>"; };
A99789871CD3D4E2005E7DAC /* Hologram.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = Hologram.vert; sourceTree = "<group>"; };
A99789881CD3D4E2005E7DAC /* Main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Main.cpp; sourceTree = "<group>"; };
A99789891CD3D4E2005E7DAC /* Meshes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Meshes.cpp; sourceTree = "<group>"; };
A997898A1CD3D4E2005E7DAC /* Meshes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Meshes.h; sourceTree = "<group>"; };
@ -88,8 +80,6 @@
A9B67B8A1C3AAEA200373FFD /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
A9B67B8B1C3AAEA200373FFD /* macOS.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = macOS.xcassets; sourceTree = "<group>"; };
A9C2AB97218503A400DDBC03 /* libMoltenVK.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libMoltenVK.a; path = ../../../MoltenVK/iOS/static/libMoltenVK.a; sourceTree = "<group>"; };
A9C2AB98218503A400DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MoltenVKGLSLToSPIRVConverter.framework; path = ../../../MoltenVKShaderConverter/MoltenVKGLSLToSPIRVConverter/iOS/framework/MoltenVKGLSLToSPIRVConverter.framework; sourceTree = "<group>"; };
A9C2AB9B218503BA00DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MoltenVKGLSLToSPIRVConverter.framework; path = ../../../MoltenVKShaderConverter/MoltenVKGLSLToSPIRVConverter/macOS/framework/MoltenVKGLSLToSPIRVConverter.framework; sourceTree = "<group>"; };
A9C2AB9C218503BA00DDBC03 /* libMoltenVK.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libMoltenVK.a; path = ../../../MoltenVK/macOS/static/libMoltenVK.a; sourceTree = "<group>"; };
A9D516F61CD575E300097D96 /* HelpersDispatchTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HelpersDispatchTable.cpp; sourceTree = "<group>"; };
A9D516F71CD575E300097D96 /* HelpersDispatchTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HelpersDispatchTable.h; sourceTree = "<group>"; };
@ -101,7 +91,6 @@
buildActionMask = 2147483647;
files = (
A9C2AB99218503A400DDBC03 /* libMoltenVK.a in Frameworks */,
A9C2AB9A218503A400DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -110,7 +99,6 @@
buildActionMask = 2147483647;
files = (
A9C2AB9E218503BA00DDBC03 /* libMoltenVK.a in Frameworks */,
A9C2AB9D218503BA00DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -147,10 +135,10 @@
A997897F1CD3D4E2005E7DAC /* Game.h */,
A99789821CD3D4E2005E7DAC /* Helpers.h */,
A99789831CD3D4E2005E7DAC /* Hologram.cpp */,
A99789841CD3D4E2005E7DAC /* Hologram.frag */,
A99789851CD3D4E2005E7DAC /* Hologram.h */,
A99789861CD3D4E2005E7DAC /* Hologram.push_constant.vert */,
A99789871CD3D4E2005E7DAC /* Hologram.vert */,
A93374662284CD260059D36E /* Hologram.frag.h */,
A93374652284CD260059D36E /* Hologram.push_constant.vert.h */,
A93374642284CD260059D36E /* Hologram.vert.h */,
A99789881CD3D4E2005E7DAC /* Main.cpp */,
A99789891CD3D4E2005E7DAC /* Meshes.cpp */,
A997898A1CD3D4E2005E7DAC /* Meshes.h */,
@ -220,9 +208,7 @@
isa = PBXGroup;
children = (
A9C2AB9C218503BA00DDBC03 /* libMoltenVK.a */,
A9C2AB9B218503BA00DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework */,
A9C2AB97218503A400DDBC03 /* libMoltenVK.a */,
A9C2AB98218503A400DDBC03 /* MoltenVKGLSLToSPIRVConverter.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -312,12 +298,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A99789B51CD3D4E2005E7DAC /* Hologram.vert in Resources */,
A9B67B7F1C3AAE9800373FFD /* Icon.png in Resources */,
A99789B31CD3D4E2005E7DAC /* Hologram.push_constant.vert in Resources */,
A9B67B801C3AAE9800373FFD /* Main.storyboard in Resources */,
A9B67B7E1C3AAE9800373FFD /* Default~ipad.png in Resources */,
A99789B11CD3D4E2005E7DAC /* Hologram.frag in Resources */,
A9B67B7D1C3AAE9800373FFD /* Default-568h@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -327,10 +310,7 @@
buildActionMask = 2147483647;
files = (
A9B67B911C3AAEA200373FFD /* macOS.xcassets in Resources */,
A99789B21CD3D4E2005E7DAC /* Hologram.frag in Resources */,
A9B67B901C3AAEA200373FFD /* Main.storyboard in Resources */,
A99789B41CD3D4E2005E7DAC /* Hologram.push_constant.vert in Resources */,
A99789B61CD3D4E2005E7DAC /* Hologram.vert in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -379,9 +359,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVKShaderConverter/MoltenVKGLSLToSPIRVConverter/iOS/framework\"";
GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVK/iOS/static\"";
@ -396,9 +374,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVKShaderConverter/MoltenVKGLSLToSPIRVConverter/iOS/framework\"";
GCC_PREFIX_HEADER = "$(SRCROOT)/iOS/Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVK/iOS/static\"";
@ -413,9 +389,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVKShaderConverter/MoltenVKGLSLToSPIRVConverter/macOS/framework\"";
GCC_PREFIX_HEADER = "$(SRCROOT)/macOS/Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist";
LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVK/macOS/static\"";
MACOSX_DEPLOYMENT_TARGET = 10.11;
@ -432,9 +406,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVKShaderConverter/MoltenVKGLSLToSPIRVConverter/macOS/framework\"";
GCC_PREFIX_HEADER = "$(SRCROOT)/macOS/Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)";
INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist";
LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../MoltenVK/macOS/static\"";
MACOSX_DEPLOYMENT_TARGET = 10.11;
@ -463,7 +435,6 @@
"DEBUG=1",
_DEBUG,
GLM_FORCE_RADIANS,
MVK_USE_MOLTENVK_SHADER_CONVERTER,
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
@ -471,7 +442,6 @@
HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/../../../MoltenVK/include\"",
"\"$(SRCROOT)/../VulkanSamples/API-Samples/utils\"",
"\"$(SRCROOT)/../../../MoltenVKShaderConverter/include\"",
);
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC";
@ -490,17 +460,13 @@
ENABLE_BITCODE = NO;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
GLM_FORCE_RADIANS,
MVK_USE_MOLTENVK_SHADER_CONVERTER,
);
GCC_PREPROCESSOR_DEFINITIONS = GLM_FORCE_RADIANS;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
HEADER_SEARCH_PATHS = (
"\"$(SRCROOT)/../../../MoltenVK/include\"",
"\"$(SRCROOT)/../VulkanSamples/API-Samples/utils\"",
"\"$(SRCROOT)/../../../MoltenVKShaderConverter/include\"",
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.moltenvk.${PRODUCT_NAME:identifier}";

View File

@ -109,12 +109,6 @@ The demo allows some customization, by modifying the arguments passed to the dem
To customize, modify the arguments created in the `DemoViewController viewDidLoad` method
found in the `iOS/DemoViewController.mm` or `macOS/DemoViewController.mm` file.
This demo illustrates the use of the **MoltenVK** API `vkGetMoltenVKDeviceConfigurationMVK()`
and `vkSetMoltenVKDeviceConfigurationMVK()` functions to enable **MoltenVK** debugging, including
logging the conversion of shaders from *SPIR-V* to *Metal Shading Language*. See the use of these
functions in the `Hologram/Hologram.cpp` file. To see the effect, modify the `Hologram-iOS` or
`Hologram-macOS` *Scheme* from within *Xcode* to use the **Debug** *Build Configuration* setting.
The `Hologram` demo is a simple example of installing **MoltenVK** as a *static library*.

View File

@ -260,6 +260,7 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following
- `VK_AMD_gpu_shader_half_float`
- `VK_AMD_negative_viewport_height`
- `VK_IMG_format_pvrtc` (iOS)
- `VK_NV_glsl_shader`
In order to visibly display your content on *iOS* or *macOS*, you must enable the `VK_MVK_ios_surface`
or `VK_MVK_macos_surface` extension, respectively, and use the functions defined for that extension

View File

@ -19,6 +19,7 @@ MoltenVK 1.0.35
Released TBD
- Support the `VK_EXT_debug_report` extension.
- Support the `VK_NV_glsl_shader` extension.
- Change log indication of error in logs from `[***MoltenVK ERROR***]` to
`[mvk-error]`, for consistency with other log level indications.
- Tessellation fixes:

View File

@ -1 +1 @@
07b1ccd82ff6b7e6369a0d8d6a5e5e4f7ba0b7d6
37e808988e758ec4f6f689012fb425bab1398ecf

View File

@ -222,6 +222,20 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
A96B8156227BF6FD008A772B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A9C86CB61C55B8350096CAF2 /* MoltenVKShaderConverter.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = A937472B1A9A8B2900F29B34;
remoteInfo = "MoltenVKGLSLToSPIRVConverter-iOS";
};
A96B8158227BF715008A772B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A9C86CB61C55B8350096CAF2 /* MoltenVKShaderConverter.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = A93747701A9A98D000F29B34;
remoteInfo = "MoltenVKGLSLToSPIRVConverter-macOS";
};
A981497B1FB6B566005F00B4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A9C86CB61C55B8350096CAF2 /* MoltenVKShaderConverter.xcodeproj */;
@ -763,6 +777,7 @@
);
dependencies = (
A981499B1FB6B9CF005F00B4 /* PBXTargetDependency */,
A96B8157227BF6FD008A772B /* PBXTargetDependency */,
);
name = "MoltenVK-iOS";
productName = MoltenVK;
@ -782,6 +797,7 @@
);
dependencies = (
A98149A41FB6B9EB005F00B4 /* PBXTargetDependency */,
A96B8159227BF715008A772B /* PBXTargetDependency */,
);
name = "MoltenVK-macOS";
productName = MoltenVK;
@ -1048,6 +1064,16 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
A96B8157227BF6FD008A772B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "MoltenVKGLSLToSPIRVConverter-iOS";
targetProxy = A96B8156227BF6FD008A772B /* PBXContainerItemProxy */;
};
A96B8159227BF715008A772B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "MoltenVKGLSLToSPIRVConverter-macOS";
targetProxy = A96B8158227BF715008A772B /* PBXContainerItemProxy */;
};
A981499B1FB6B9CF005F00B4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "MVKSPIRVToMSLConverter-iOS";
@ -1157,7 +1183,7 @@
MACH_O_TYPE = staticlib;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRELINK_LIBS = "${CONFIGURATION_BUILD_DIR}/libMoltenVKSPIRVToMSLConverter.a";
PRELINK_LIBS = "${CONFIGURATION_BUILD_DIR}/libMoltenVKSPIRVToMSLConverter.a ${CONFIGURATION_BUILD_DIR}/libMoltenVKGLSLToSPIRVConverter.a";
PRODUCT_NAME = MoltenVK;
SKIP_INSTALL = YES;
};
@ -1214,7 +1240,7 @@
);
MACH_O_TYPE = staticlib;
MTL_ENABLE_DEBUG_INFO = NO;
PRELINK_LIBS = "${CONFIGURATION_BUILD_DIR}/libMoltenVKSPIRVToMSLConverter.a";
PRELINK_LIBS = "${CONFIGURATION_BUILD_DIR}/libMoltenVKSPIRVToMSLConverter.a ${CONFIGURATION_BUILD_DIR}/libMoltenVKGLSLToSPIRVConverter.a";
PRODUCT_NAME = MoltenVK;
SKIP_INSTALL = YES;
VALIDATE_PRODUCT = YES;

View File

@ -566,6 +566,7 @@ typedef struct {
MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */
MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction. */
MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline. */
MVKPerformanceTracker glslToSPRIV; /** Convert GLSL to SPIR-V code. */
} MVKShaderCompilationPerformance;

View File

@ -703,7 +703,7 @@ bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLRenderPipelineDescriptor*
addVertexInputToShaderConverterContext(shaderContext, pCreateInfo);
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pVertexSS->module)->getMTLFunction(&shaderContext, _pVertexSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader function could not be compiled into pipeline. See previous logged error."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Vertex shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
plDesc.vertexFunction = mtlFunction;
@ -712,16 +712,16 @@ bool MVKGraphicsPipeline::addVertexShaderToPipeline(MTLRenderPipelineDescriptor*
_needsVertexOutputBuffer = shaderContext.options.needsOutputBuffer;
// If we need the auxiliary buffer and there's no place to put it, we're in serious trouble.
if (_needsVertexAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires auxiliary buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Vertex shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
// Ditto captured output buffer.
if (_needsVertexOutputBuffer && _outputBufferIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires output buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Vertex shader requires output buffer, but there is no free slot to pass it."));
return false;
}
if (_needsVertexOutputBuffer && _indirectParamsIndex.stages[kMVKShaderStageVertex] >= _device->_pMetalFeatures->maxPerStageBufferCount - vbCnt) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Vertex shader requires indirect parameters buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Vertex shader requires indirect parameters buffer, but there is no free slot to pass it."));
return false;
}
return true;
@ -739,7 +739,7 @@ bool MVKGraphicsPipeline::addTessCtlShaderToPipeline(MTLComputePipelineDescripto
addPrevStageOutputToShaderConverterContext(shaderContext, vtxOutputs);
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessCtlSS->module)->getMTLFunction(&shaderContext, _pTessCtlSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader function could not be compiled into pipeline. See previous logged error."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation control shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
plDesc.computeFunction = mtlFunction;
@ -748,23 +748,23 @@ bool MVKGraphicsPipeline::addTessCtlShaderToPipeline(MTLComputePipelineDescripto
_needsTessCtlPatchOutputBuffer = shaderContext.options.needsPatchOutputBuffer;
_needsTessCtlInput = shaderContext.options.needsInputThreadgroupMem;
if (_needsTessCtlAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires auxiliary buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation control shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
if (_indirectParamsIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires indirect parameters buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation control shader requires indirect parameters buffer, but there is no free slot to pass it."));
return false;
}
if (_needsTessCtlOutputBuffer && _outputBufferIndex.stages[kMVKShaderStageTessCtl] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires per-vertex output buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation control shader requires per-vertex output buffer, but there is no free slot to pass it."));
return false;
}
if (_needsTessCtlPatchOutputBuffer && _tessCtlPatchOutputBufferIndex >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires per-patch output buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation control shader requires per-patch output buffer, but there is no free slot to pass it."));
return false;
}
if (_tessCtlLevelBufferIndex >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessCtlNumReservedBuffers) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation control shader requires tessellation level output buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation control shader requires tessellation level output buffer, but there is no free slot to pass it."));
return false;
}
return true;
@ -779,7 +779,7 @@ bool MVKGraphicsPipeline::addTessEvalShaderToPipeline(MTLRenderPipelineDescripto
addPrevStageOutputToShaderConverterContext(shaderContext, tcOutputs);
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pTessEvalSS->module)->getMTLFunction(&shaderContext, _pTessEvalSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation evaluation shader function could not be compiled into pipeline. See previous logged error."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation evaluation shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
// Yeah, you read that right. Tess. eval functions are a kind of vertex function in Metal.
@ -788,7 +788,7 @@ bool MVKGraphicsPipeline::addTessEvalShaderToPipeline(MTLRenderPipelineDescripto
_needsTessEvalAuxBuffer = shaderContext.options.needsAuxBuffer;
// If we need the auxiliary buffer and there's no place to put it, we're in serious trouble.
if (_needsTessEvalAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageTessEval] >= _device->_pMetalFeatures->maxPerStageBufferCount - kMVKTessEvalNumReservedBuffers) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Tessellation evaluation shader requires auxiliary buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Tessellation evaluation shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
return true;
@ -802,13 +802,13 @@ bool MVKGraphicsPipeline::addFragmentShaderToPipeline(MTLRenderPipelineDescripto
shaderContext.options.shouldCaptureOutput = false;
id<MTLFunction> mtlFunction = ((MVKShaderModule*)_pFragmentSS->module)->getMTLFunction(&shaderContext, _pFragmentSS->pSpecializationInfo, _pipelineCache).mtlFunction;
if ( !mtlFunction ) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader function could not be compiled into pipeline. See previous logged error."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Fragment shader function could not be compiled into pipeline. See previous logged error."));
return false;
}
plDesc.fragmentFunction = mtlFunction;
_needsFragmentAuxBuffer = shaderContext.options.needsAuxBuffer;
if (_needsFragmentAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageFragment] >= _device->_pMetalFeatures->maxPerStageBufferCount) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Fragment shader requires auxiliary buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Fragment shader requires auxiliary buffer, but there is no free slot to pass it."));
return false;
}
}
@ -1170,11 +1170,11 @@ MVKComputePipeline::MVKComputePipeline(MVKDevice* device,
_mtlPipelineState = plc->newMTLComputePipelineState(shaderFunc.mtlFunction); // retained
plc->destroy();
} else {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Compute shader function could not be compiled into pipeline. See previous logged error."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Compute shader function could not be compiled into pipeline. See previous logged error."));
}
if (_needsAuxBuffer && _auxBufferIndex.stages[kMVKShaderStageCompute] > _device->_pMetalFeatures->maxPerStageBufferCount) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Compute shader requires auxiliary buffer, but there is no free slot to pass it."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "Compute shader requires auxiliary buffer, but there is no free slot to pass it."));
}
}

View File

@ -21,6 +21,7 @@
#include "MVKDevice.h"
#include "MVKSync.h"
#include <MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.h>
#include <MoltenVKGLSLToSPIRVConverter/GLSLToSPIRVConverter.h>
#include <vector>
#include <mutex>
@ -167,22 +168,22 @@ public:
bool convert(SPIRVToMSLConverterContext* pContext);
/** Returns the original SPIR-V code that was specified when this object was created. */
inline const std::vector<uint32_t>& getSPIRV() { return _converter.getSPIRV(); }
const std::vector<uint32_t>& getSPIRV() { return _spvConverter.getSPIRV(); }
/**
* Returns the Metal Shading Language source code as converted by the most recent
* call to convert() function, or set directly using the setMSL() function.
*/
inline const std::string& getMSL() { return _converter.getMSL(); }
const std::string& getMSL() { return _spvConverter.getMSL(); }
/**
* Returns information about the shader entry point as converted by the most recent
* call to convert() function, or set directly using the setMSL() function.
*/
inline const SPIRVEntryPoint& getEntryPoint() { return _converter.getEntryPoint(); }
const SPIRVEntryPoint& getEntryPoint() { return _spvConverter.getEntryPoint(); }
/** Returns a key as a means of identifying this shader module in a pipeline cache. */
inline MVKShaderModuleKey getKey() { return _key; }
MVKShaderModuleKey getKey() { return _key; }
MVKShaderModule(MVKDevice* device, const VkShaderModuleCreateInfo* pCreateInfo);
@ -191,8 +192,11 @@ public:
protected:
friend MVKShaderCacheIterator;
MVKGLSLConversionShaderStage getMVKGLSLConversionShaderStage(SPIRVToMSLConverterContext* pContext);
MVKShaderLibraryCache _shaderLibraryCache;
SPIRVToMSLConverter _converter;
SPIRVToMSLConverter _spvConverter;
GLSLToSPIRVConverter _glslConverter;
MVKShaderLibrary* _defaultLibrary;
MVKShaderModuleKey _key;
std::mutex _accessLock;

View File

@ -92,7 +92,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
}
}
} else {
reportError(VK_ERROR_INITIALIZATION_FAILED, "Shader module does not contain an entry point named '%s'.", mtlFuncName.UTF8String);
reportError(VK_ERROR_INVALID_SHADER_NV, "Shader module does not contain an entry point named '%s'.", mtlFuncName.UTF8String);
}
return { mtlFunc, MTLSizeMake(getWorkgroupDimensionSize(_entryPoint.workgroupSize.width, pSpecializationInfo),
@ -150,7 +150,7 @@ void MVKShaderLibrary::handleCompilationError(NSError* err, const char* opDesc)
if (_mtlLibrary) {
MVKLogInfo("%s succeeded with warnings (Error code %li):\n%s", opDesc, (long)err.code, err.localizedDescription.UTF8String);
} else {
_owner->setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED,
_owner->setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV,
"%s failed (Error code %li):\n%s",
opDesc, (long)err.code,
err.localizedDescription.UTF8String));
@ -244,19 +244,53 @@ MVKMTLFunction MVKShaderModule::getMTLFunction(SPIRVToMSLConverterContext* pCont
bool MVKShaderModule::convert(SPIRVToMSLConverterContext* pContext) {
bool shouldLogCode = _device->_pMVKConfig->debugMode;
bool shouldLogEstimatedGLSL = shouldLogCode;
// If the SPIR-V converter does not have any code, but the GLSL converter does,
// convert the GLSL code to SPIR-V and set it into the SPIR-V conveter.
if ( !_spvConverter.hasSPIRV() && _glslConverter.hasGLSL() ) {
uint64_t startTime = _device->getPerformanceTimestamp();
bool wasConverted = _converter.convert(*pContext, shouldLogCode, shouldLogCode, shouldLogCode);
bool wasConverted = _glslConverter.convert(getMVKGLSLConversionShaderStage(pContext), shouldLogCode, false);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.glslToSPRIV, startTime);
if (wasConverted) {
if (shouldLogCode) { MVKLogInfo("%s", _glslConverter.getResultLog().c_str()); }
_spvConverter.setSPIRV(_glslConverter.getSPIRV());
} else {
reportError(VK_ERROR_INVALID_SHADER_NV, "Unable to convert GLSL to SPIR-V:\n%s", _glslConverter.getResultLog().c_str());
}
shouldLogEstimatedGLSL = false;
}
uint64_t startTime = _device->getPerformanceTimestamp();
bool wasConverted = _spvConverter.convert(*pContext, shouldLogCode, shouldLogCode, shouldLogEstimatedGLSL);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.spirvToMSL, startTime);
if (wasConverted) {
if (shouldLogCode) { MVKLogInfo("%s", _converter.getResultLog().data()); }
if (shouldLogCode) { MVKLogInfo("%s", _spvConverter.getResultLog().c_str()); }
} else {
reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "Unable to convert SPIR-V to MSL:\n%s", _converter.getResultLog().data());
reportError(VK_ERROR_INVALID_SHADER_NV, "Unable to convert SPIR-V to MSL:\n%s", _spvConverter.getResultLog().c_str());
}
return wasConverted;
}
// Returns the MVKGLSLConversionShaderStage corresponding to the shader stage in the SPIR-V converter context.
MVKGLSLConversionShaderStage MVKShaderModule::getMVKGLSLConversionShaderStage(SPIRVToMSLConverterContext* pContext) {
switch (pContext->options.entryPointStage) {
case spv::ExecutionModelVertex: return kMVKGLSLConversionShaderStageVertex;
case spv::ExecutionModelTessellationControl: return kMVKGLSLConversionShaderStageTessControl;
case spv::ExecutionModelTessellationEvaluation: return kMVKGLSLConversionShaderStageTessEval;
case spv::ExecutionModelGeometry: return kMVKGLSLConversionShaderStageGeometry;
case spv::ExecutionModelFragment: return kMVKGLSLConversionShaderStageFragment;
case spv::ExecutionModelGLCompute: return kMVKGLSLConversionShaderStageCompute;
case spv::ExecutionModelKernel: return kMVKGLSLConversionShaderStageCompute;
default:
MVKAssert(false, "Bad shader stage provided for GLSL to SPIR-V conversion.");
return kMVKGLSLConversionShaderStageAuto;
}
}
#pragma mark Construction
@ -270,7 +304,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
// Ensure something is there.
if ( (pCreateInfo->pCode == VK_NULL_HANDLE) || (codeSize < 4) ) {
setConfigurationResult(reportError(VK_INCOMPLETE, "Shader module contains no SPIR-V code."));
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "vkCreateShaderModule(): Shader module contains no shader code."));
return;
}
@ -280,35 +314,35 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
uint32_t magicNum = *pCreateInfo->pCode;
switch (magicNum) {
case kMVKMagicNumberSPIRVCode: { // SPIR-V code
size_t spvCount = (pCreateInfo->codeSize + 3) >> 2; // Round up if byte length not exactly on uint32_t boundary
size_t spvCount = (codeSize + 3) >> 2; // Round up if byte length not exactly on uint32_t boundary
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(pCreateInfo->pCode, spvCount);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
_converter.setSPIRV(pCreateInfo->pCode, spvCount);
_spvConverter.setSPIRV(pCreateInfo->pCode, spvCount);
break;
}
case kMVKMagicNumberMSLSourceCode: { // MSL source code
size_t hdrSize = sizeof(MVKMSLSPIRVHeader);
char* pMSLCode = (char*)(uintptr_t(pCreateInfo->pCode) + hdrSize);
size_t mslCodeLen = pCreateInfo->codeSize - hdrSize;
size_t mslCodeLen = codeSize - hdrSize;
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(&magicNum);
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
_converter.setMSL(pMSLCode, nullptr);
_defaultLibrary = new MVKShaderLibrary(this, _converter.getMSL().c_str(), _converter.getEntryPoint());
_spvConverter.setMSL(pMSLCode, nullptr);
_defaultLibrary = new MVKShaderLibrary(this, _spvConverter.getMSL().c_str(), _spvConverter.getEntryPoint());
break;
}
case kMVKMagicNumberMSLCompiledCode: { // MSL compiled binary code
size_t hdrSize = sizeof(MVKMSLSPIRVHeader);
char* pMSLCode = (char*)(uintptr_t(pCreateInfo->pCode) + hdrSize);
size_t mslCodeLen = pCreateInfo->codeSize - hdrSize;
size_t mslCodeLen = codeSize - hdrSize;
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(&magicNum);
@ -319,8 +353,19 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
break;
}
default:
setConfigurationResult(reportError(VK_ERROR_FORMAT_NOT_SUPPORTED, "SPIR-V contains invalid magic number %x.", magicNum));
default: // Could be GLSL source code
if (_device->_enabledExtensions.vk_NV_glsl_shader.enabled) {
const char* pGLSL = (char*)pCreateInfo->pCode;
size_t glslLen = codeSize - 1;
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(pGLSL, codeSize);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
_glslConverter.setGLSL(pGLSL, glslLen);
} else {
setConfigurationResult(reportError(VK_ERROR_INVALID_SHADER_NV, "vkCreateShaderModule(): The SPIR-V contains an invalid magic number %x.", magicNum));
}
break;
}

View File

@ -63,7 +63,8 @@ MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE)
MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK)
MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT)
MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT)
MVK_EXTENSION_LAST(IMG_format_pvrtc, IMG_FORMAT_PVRTC)
MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC)
MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER)
#undef MVK_EXTENSION
#undef MVK_EXTENSION_LAST

View File

@ -32,14 +32,14 @@ extern "C" {
/** Enumeration of the pipeline stages for which a shader can be compiled. */
typedef enum {
kMVKShaderStageAuto,
kMVKShaderStageVertex,
kMVKShaderStageTessControl,
kMVKShaderStageTessEval,
kMVKShaderStageGeometry,
kMVKShaderStageFragment,
kMVKShaderStageCompute,
} MVKShaderStage;
kMVKGLSLConversionShaderStageAuto,
kMVKGLSLConversionShaderStageVertex,
kMVKGLSLConversionShaderStageTessControl,
kMVKGLSLConversionShaderStageTessEval,
kMVKGLSLConversionShaderStageGeometry,
kMVKGLSLConversionShaderStageFragment,
kMVKGLSLConversionShaderStageCompute,
} MVKGLSLConversionShaderStage;
/**
@ -63,7 +63,7 @@ typedef enum {
* should be logged to the converter results log. This can be useful during shader debugging.
*/
bool mvkConvertGLSLToSPIRV(const char* glslSource,
MVKShaderStage shaderStage,
MVKGLSLConversionShaderStage shaderStage,
uint32_t** pSPIRVCode,
size_t *pSPIRVLength,
char** pResultLog,
@ -90,7 +90,7 @@ bool mvkConvertGLSLToSPIRV(const char* glslSource,
* should be logged to the converter results log. This can be useful during shader debugging.
*/
bool mvkConvertGLSLFileToSPIRV(const char* glslFilepath,
MVKShaderStage shaderStage,
MVKGLSLConversionShaderStage shaderStage,
uint32_t** pSPIRVCode,
size_t *pSPIRVLength,
char** pResultLog,

View File

@ -26,7 +26,7 @@ using namespace mvk;
MVK_PUBLIC_SYMBOL bool mvkConvertGLSLToSPIRV(const char* glslSource,
MVKShaderStage shaderStage,
MVKGLSLConversionShaderStage shaderStage,
uint32_t** pSPIRVCode,
size_t *pSPIRVLength,
char** pResultLog,
@ -59,7 +59,7 @@ MVK_PUBLIC_SYMBOL bool mvkConvertGLSLToSPIRV(const char* glslSource,
}
MVK_PUBLIC_SYMBOL bool mvkConvertGLSLFileToSPIRV(const char* glslFilepath,
MVKShaderStage shaderStage,
MVKGLSLConversionShaderStage shaderStage,
uint32_t** pSPIRVCode,
size_t *pSPIRVLength,
char** pResultLog,

View File

@ -37,13 +37,9 @@ using namespace mvk;
void configureGLSLCompilerResources(TBuiltInResource* glslCompilerResources);
/** Returns the GLSL compiler language type corresponding to the specified MoltenVK shader stage. */
EShLanguage eshLanguageFromMVKShaderStage(const MVKShaderStage mvkShaderStage);
EShLanguage eshLanguageFromMVKGLSLConversionShaderStage(const MVKGLSLConversionShaderStage mvkShaderStage);
MVK_PUBLIC_SYMBOL void GLSLToSPIRVConverter::setGLSL(const string& glslSrc) { _glsl = glslSrc; }
MVK_PUBLIC_SYMBOL const string& GLSLToSPIRVConverter::getGLSL() { return _glsl; }
MVK_PUBLIC_SYMBOL bool GLSLToSPIRVConverter::convert(MVKShaderStage shaderStage,
MVK_PUBLIC_SYMBOL bool GLSLToSPIRVConverter::convert(MVKGLSLConversionShaderStage shaderStage,
bool shouldLogGLSL,
bool shouldLogSPIRV) {
_wasConverted = true;
@ -54,7 +50,7 @@ MVK_PUBLIC_SYMBOL bool GLSLToSPIRVConverter::convert(MVKShaderStage shaderStage,
EShMessages messages = (EShMessages)(EShMsgDefault | EShMsgSpvRules | EShMsgVulkanRules);
EShLanguage stage = eshLanguageFromMVKShaderStage(shaderStage);
EShLanguage stage = eshLanguageFromMVKGLSLConversionShaderStage(shaderStage);
TBuiltInResource glslCompilerResources;
configureGLSLCompilerResources(&glslCompilerResources);
const char *glslStrings[1];
@ -91,12 +87,6 @@ MVK_PUBLIC_SYMBOL bool GLSLToSPIRVConverter::convert(MVKShaderStage shaderStage,
return _wasConverted;
}
MVK_PUBLIC_SYMBOL const vector<uint32_t>& GLSLToSPIRVConverter::getSPIRV() { return _spirv; }
MVK_PUBLIC_SYMBOL bool GLSLToSPIRVConverter::getWasConverted() { return _wasConverted; }
MVK_PUBLIC_SYMBOL const string& GLSLToSPIRVConverter::getResultLog() { return _resultLog; }
/** Appends the message text to the result log. */
void GLSLToSPIRVConverter::logMsg(const char* logMsg) {
string trimMsg = trim(logMsg);
@ -240,14 +230,14 @@ void configureGLSLCompilerResources(TBuiltInResource* glslCompilerResources) {
glslCompilerResources->limits.generalConstantMatrixVectorIndexing = 1;
}
EShLanguage eshLanguageFromMVKShaderStage(const MVKShaderStage mvkShaderStage) {
EShLanguage eshLanguageFromMVKGLSLConversionShaderStage(const MVKGLSLConversionShaderStage mvkShaderStage) {
switch (mvkShaderStage) {
case kMVKShaderStageVertex: return EShLangVertex;
case kMVKShaderStageTessControl: return EShLangTessControl;
case kMVKShaderStageTessEval: return EShLangTessEvaluation;
case kMVKShaderStageGeometry: return EShLangGeometry;
case kMVKShaderStageFragment: return EShLangFragment;
case kMVKShaderStageCompute: return EShLangCompute;
case kMVKGLSLConversionShaderStageVertex: return EShLangVertex;
case kMVKGLSLConversionShaderStageTessControl: return EShLangTessControl;
case kMVKGLSLConversionShaderStageTessEval: return EShLangTessEvaluation;
case kMVKGLSLConversionShaderStageGeometry: return EShLangGeometry;
case kMVKGLSLConversionShaderStageFragment: return EShLangFragment;
case kMVKGLSLConversionShaderStageCompute: return EShLangCompute;
default: return EShLangVertex;
}
}

View File

@ -35,11 +35,20 @@ namespace mvk {
public:
/** Sets the GLSL source code that is to be converted to the specified null-terminated string. */
void setGLSL(const std::string& glslSrc);
/** Sets the GLSL source code that is to be converted to the specified string. */
void setGLSL(const std::string& glslSrc) { _glsl = glslSrc; }
/**
* Sets the GLSL source code that is to be converted from the first length characters
* of the buffer, and ensuring the resulting string is null-terminated.
*/
void setGLSL(const char* glslSrc, size_t length) { _glsl.assign(glslSrc, length); }
/** Returns the GLSL source code that was set using the setGLSL() function. */
const std::string& getGLSL();
const std::string& getGLSL() { return _glsl; }
/** Returns whether the SPIR-V code has been set. */
bool hasGLSL() { return !_glsl.empty(); }
/**
* Converts GLSL code, set with setGLSL(), to SPIR-V code, which can be retrieved using getSPIRV().
@ -47,23 +56,23 @@ namespace mvk {
* The boolean flags indicate whether the original GLSL code and resulting SPIR-V code should
* be logged to the result log of this converter. This can be useful during shader debugging.
*/
bool convert(MVKShaderStage shaderStage, bool shouldLogGLSL, bool shouldLogSPIRV);
/** Returns the SPIRV code most recently converted by the convert() function. */
const std::vector<uint32_t>& getSPIRV();
bool convert(MVKGLSLConversionShaderStage shaderStage, bool shouldLogGLSL, bool shouldLogSPIRV);
/**
* Returns whether the most recent conversion was successful.
*
* The initial value of this property is NO. It is set to YES upon successful conversion.
*/
bool getWasConverted();
bool wasConverted() { return _wasConverted; }
/** Returns the SPIRV code most recently converted by the convert() function. */
const std::vector<uint32_t>& getSPIRV() { return _spirv; }
/**
* Returns a human-readable log of the most recent conversion activity.
* This may be empty if the conversion was successful.
*/
const std::string& getResultLog();
const std::string& getResultLog() { return _resultLog; }
protected:
void logMsg(const char* logMsg);

View File

@ -197,8 +197,6 @@ SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::Platform getCompilerMSLPlatform(SPI
// Populates the entry point with info extracted from the SPRI-V compiler.
void populateEntryPoint(SPIRVEntryPoint& entryPoint, SPIRV_CROSS_NAMESPACE::Compiler* pCompiler, SPIRVToMSLConverterOptions& options);
MVK_PUBLIC_SYMBOL void SPIRVToMSLConverter::setSPIRV(const vector<uint32_t>& spirv) { _spirv = spirv; }
MVK_PUBLIC_SYMBOL void SPIRVToMSLConverter::setSPIRV(const uint32_t* spirvCode, size_t length) {
_spirv.clear(); // Clear for reuse
_spirv.reserve(length);
@ -207,8 +205,6 @@ MVK_PUBLIC_SYMBOL void SPIRVToMSLConverter::setSPIRV(const uint32_t* spirvCode,
}
}
MVK_PUBLIC_SYMBOL const vector<uint32_t>& SPIRVToMSLConverter::getSPIRV() { return _spirv; }
MVK_PUBLIC_SYMBOL bool SPIRVToMSLConverter::convert(SPIRVToMSLConverterContext& context,
bool shouldLogSPIRV,
bool shouldLogMSL,

View File

@ -225,7 +225,7 @@ namespace mvk {
public:
/** Sets the SPIRV code. */
void setSPIRV(const std::vector<uint32_t>& spirv);
void setSPIRV(const std::vector<uint32_t>& spirv) { _spirv = spirv; }
/**
* Sets the SPIRV code from the specified array of values.
@ -234,7 +234,10 @@ namespace mvk {
void setSPIRV(const uint32_t* spirvCode, size_t length);
/** Returns a reference to the SPIRV code, set by one of the setSPIRV() functions. */
const std::vector<uint32_t>& getSPIRV();
const std::vector<uint32_t>& getSPIRV() { return _spirv; }
/** Returns whether the SPIR-V code has been set. */
bool hasSPIRV() { return !_spirv.empty(); }
/**
* Converts SPIR-V code, set using setSPIRV() to MSL code, which can be retrieved using getMSL().
@ -248,6 +251,13 @@ namespace mvk {
bool shouldLogMSL = false,
bool shouldLogGLSL = false);
/**
* Returns whether the most recent conversion was successful.
*
* The initial value of this property is NO. It is set to YES upon successful conversion.
*/
bool wasConverted() { return _wasConverted; }
/**
* Returns the Metal Shading Language source code most recently converted
* by the convert() function, or set directly using the setMSL() function.
@ -257,13 +267,6 @@ namespace mvk {
/** Returns information about the shader entry point. */
const SPIRVEntryPoint& getEntryPoint() { return _entryPoint; }
/**
* Returns whether the most recent conversion was successful.
*
* The initial value of this property is NO. It is set to YES upon successful conversion.
*/
bool getWasConverted() { return _wasConverted; }
/**
* Returns a human-readable log of the most recent conversion activity.
* This may be empty if the conversion was successful.

View File

@ -84,7 +84,7 @@ bool MoltenVKShaderConverterTool::processFile(string filePath) {
string pathExtn = pathExtension(absPath);
if (_shouldReadGLSL && isGLSLFileExtension(pathExtn)) {
return convertGLSL(absPath, emptyPath, emptyPath, kMVKShaderStageAuto);
return convertGLSL(absPath, emptyPath, emptyPath, kMVKGLSLConversionShaderStageAuto);
} else if (_shouldReadSPIRV && isSPIRVFileExtension(pathExtn)) {
return convertSPIRV(absPath, emptyPath);
}
@ -97,7 +97,7 @@ bool MoltenVKShaderConverterTool::processFile(string filePath) {
bool MoltenVKShaderConverterTool::convertGLSL(string& glslInFile,
string& spvOutFile,
string& mslOutFile,
MVKShaderStage shaderStage) {
MVKGLSLConversionShaderStage shaderStage) {
string path;
vector<char> fileContents;
string glslCode;
@ -120,11 +120,11 @@ bool MoltenVKShaderConverterTool::convertGLSL(string& glslInFile,
}
glslCode.append(fileContents.begin(), fileContents.end());
if (shaderStage == kMVKShaderStageAuto) {
if (shaderStage == kMVKGLSLConversionShaderStageAuto) {
string pathExtn = pathExtension(glslInFile);
shaderStage = shaderStageFromFileExtension(pathExtn);
}
if (shaderStage == kMVKShaderStageAuto) {
if (shaderStage == kMVKGLSLConversionShaderStageAuto) {
errMsg = "Could not determine shader type from GLSL file: " + absolutePath(path);
log(errMsg.data());
return false;
@ -254,11 +254,11 @@ bool MoltenVKShaderConverterTool::convertSPIRV(const vector<uint32_t>& spv,
}
}
MVKShaderStage MoltenVKShaderConverterTool::shaderStageFromFileExtension(string& pathExtension) {
for (auto& fx : _glslVtxFileExtns) { if (fx == pathExtension) { return kMVKShaderStageVertex; } }
for (auto& fx : _glslFragFileExtns) { if (fx == pathExtension) { return kMVKShaderStageFragment; } }
for (auto& fx : _glslCompFileExtns) { if (fx == pathExtension) { return kMVKShaderStageCompute; } }
return kMVKShaderStageAuto;
MVKGLSLConversionShaderStage MoltenVKShaderConverterTool::shaderStageFromFileExtension(string& pathExtension) {
for (auto& fx : _glslVtxFileExtns) { if (fx == pathExtension) { return kMVKGLSLConversionShaderStageVertex; } }
for (auto& fx : _glslFragFileExtns) { if (fx == pathExtension) { return kMVKGLSLConversionShaderStageFragment; } }
for (auto& fx : _glslCompFileExtns) { if (fx == pathExtension) { return kMVKGLSLConversionShaderStageCompute; } }
return kMVKGLSLConversionShaderStageAuto;
}
bool MoltenVKShaderConverterTool::isGLSLFileExtension(string& pathExtension) {
@ -372,7 +372,7 @@ MoltenVKShaderConverterTool::MoltenVKShaderConverterTool(int argc, const char* a
extractTokens(_defaultCompShaderExtns, _glslCompFileExtns);
extractTokens(_defaultSPIRVShaderExtns, _spvFileExtns);
_origPathExtnSep = "_";
_shaderStage = kMVKShaderStageAuto;
_shaderStage = kMVKGLSLConversionShaderStageAuto;
_shouldUseDirectoryRecursion = false;
_shouldReadGLSL = false;
_shouldReadSPIRV = false;
@ -482,13 +482,13 @@ bool MoltenVKShaderConverterTool::parseArgs(int argc, const char* argv[]) {
switch (shdrTypeStr.front()) {
case 'v':
_shaderStage = kMVKShaderStageVertex;
_shaderStage = kMVKGLSLConversionShaderStageVertex;
break;
case 'f':
_shaderStage = kMVKShaderStageFragment;
_shaderStage = kMVKGLSLConversionShaderStageFragment;
break;
case 'c':
_shaderStage = kMVKShaderStageCompute;
_shaderStage = kMVKGLSLConversionShaderStageCompute;
break;
default:
return false;

View File

@ -64,13 +64,13 @@ namespace mvk {
MoltenVKShaderConverterTool(int argc, const char* argv[]);
protected:
MVKShaderStage shaderStageFromFileExtension(std::string& pathExtension);
MVKGLSLConversionShaderStage shaderStageFromFileExtension(std::string& pathExtension);
bool isGLSLFileExtension(std::string& pathExtension);
bool isSPIRVFileExtension(std::string& pathExtension);
bool convertGLSL(std::string& glslInFile,
std::string& spvOutFile,
std::string& mslOutFile,
MVKShaderStage shaderStage);
MVKGLSLConversionShaderStage shaderStage);
bool convertSPIRV(std::string& spvInFile,
std::string& mslOutFile);
bool convertSPIRV(const std::vector<uint32_t>& spv,
@ -100,7 +100,7 @@ namespace mvk {
std::vector<std::string> _glslFragFileExtns;
std::vector<std::string> _glslCompFileExtns;
std::vector<std::string> _spvFileExtns;
MVKShaderStage _shaderStage;
MVKGLSLConversionShaderStage _shaderStage;
MVKPerformanceTracker _glslConversionPerformance;
MVKPerformanceTracker _spvConversionPerformance;
uint32_t _mslVersionMajor;