SPIR-V enhancements.
Fix OOM conditions with multiple consecutive two-vector OpVectorShuffles. Support non-square row-major matrix conversions. Add ability to write SPIR-V to file for debugging purposes. Update ThirdPartyConfig.md to latest use of SPIRV-Cross testability. Update to latest SPIRV-Cross version.
This commit is contained in:
parent
51193c7805
commit
03f865ea96
@ -151,39 +151,24 @@ The updated version will then be "locked in" the next time the `MoltenVK` reposi
|
||||
|
||||
### Regression Testing Your Changes to *SPIRV-Cross*
|
||||
|
||||
If you make changes to the `SPIRV-Cross` submodule, you can regression test your changes by building the
|
||||
`spirv-cross` executable and running the `test_shaders.py` regression test script, using the following steps:
|
||||
If you make changes to the `SPIRV-Cross` submodule, you can regression test your changes
|
||||
using the following steps:
|
||||
|
||||
|
||||
1. If you did not run the `External/makeAll` script, build the `SPIRV-Tools` and `glslangValidator`tools
|
||||
(you should only need to do this once):
|
||||
|
||||
cd External
|
||||
./makeSPIRVTools
|
||||
./makeglslang
|
||||
|
||||
2. Set your `PATH` environment variable so that the `spirv-cross` tool can find the
|
||||
`glslangValidator` and `SPIRV-Tools` tools:
|
||||
|
||||
export PATH=$PATH:"../glslang/build/StandAlone:../SPIRV-Tools/build/tools"
|
||||
|
||||
3. Build the `spirv-cross` executable:
|
||||
1. Load and build the versions of `SPRIV-Tools` and `glslang` that are used by the `SPIRV-Cross` tests:
|
||||
|
||||
cd External/SPIRV-Cross
|
||||
make
|
||||
./checkout_glslang_spirv_tools.sh
|
||||
|
||||
4. Run the regression tests:
|
||||
2. Run the regression tests:
|
||||
|
||||
./test_shaders.sh
|
||||
|
||||
5. If your changes result in different expected output for a reference shader, you can update
|
||||
the reference shader for a particular regression test:
|
||||
|
||||
1. Termporarily rename the existing reference shader file in `External/SPIRV-Cross/reference/shaders-msl`.
|
||||
2. Run the regression tests. A new reference shader will be automatically generated.
|
||||
3. Compare the new reference shader to the old one using a tool like *Xcode Version Editor*,
|
||||
or *Xcode FileMerge*, or equivalent.
|
||||
4. Delete the old copy of the reference shader.
|
||||
3. If your changes result in different expected output for a reference shader, and the new results
|
||||
are correct, you can update the reference shader for a particular regression test by deleting
|
||||
that reference shader, in either `External/SPIRV-Cross/reference/shaders-msl` or
|
||||
`External/SPIRV-Cross/reference/opt/shaders-msl`, and running the test again. The test will
|
||||
replace the deleted reference shader.
|
||||
|
||||
|
||||
|
||||
<a name="add_spirv-cross"></a>
|
||||
|
2
External/SPIRV-Cross
vendored
2
External/SPIRV-Cross
vendored
@ -1 +1 @@
|
||||
Subproject commit 95910ddd5aa03cbd7188fc7c107f9cc893136f10
|
||||
Subproject commit 27d4af75a0736849c046c5f068ecc80f17c1ed7e
|
@ -20,6 +20,7 @@
|
||||
#include "MVKCommandBuffer.h"
|
||||
#include "MVKBuffer.h"
|
||||
#include "MVKFoundation.h"
|
||||
#include "MVKLogging.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace std;
|
||||
@ -612,6 +613,7 @@ VkResult MVKDescriptorPool::allocateDescriptorSets(uint32_t count,
|
||||
lock_guard<mutex> lock(_lock);
|
||||
|
||||
if (_allocatedSetCount + count > _maxSets) {
|
||||
// MVKLogDebug("Pool %p could not allocate %d descriptor sets. There are alreay %d sets, and the maximum for this pool is %d.", this, count, _allocatedSetCount, _maxSets);
|
||||
return mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "The maximum number of descriptor sets that can be allocated by this descriptor pool is %d.", _maxSets);
|
||||
}
|
||||
|
||||
@ -622,6 +624,8 @@ VkResult MVKDescriptorPool::allocateDescriptorSets(uint32_t count,
|
||||
pDescriptorSets[dsIdx] = (VkDescriptorSet)mvkDescSet;
|
||||
_allocatedSetCount++;
|
||||
}
|
||||
|
||||
// MVKLogDebug("Pool %p allocating %d descriptor sets for a new total of %d sets.", this, count, _allocatedSetCount);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
@ -634,12 +638,15 @@ VkResult MVKDescriptorPool::freeDescriptorSets(uint32_t count, const VkDescripto
|
||||
_allocatedSetCount--;
|
||||
delete mvkDS;
|
||||
}
|
||||
|
||||
// MVKLogDebug("Pool %p freed %d descriptor sets for a new total of %d sets.", this, count, _allocatedSetCount);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult MVKDescriptorPool::reset(VkDescriptorPoolResetFlags flags) {
|
||||
lock_guard<mutex> lock(_lock);
|
||||
|
||||
// MVKLogDebug("Pool %p resetting and freeing remaining %d descriptor sets.", this, _allocatedSetCount);
|
||||
mvkDestroyContainerContents(_allocatedSets);
|
||||
_allocatedSetCount = 0;
|
||||
return VK_SUCCESS;
|
||||
@ -647,13 +654,17 @@ VkResult MVKDescriptorPool::reset(VkDescriptorPoolResetFlags flags) {
|
||||
|
||||
MVKDescriptorPool::MVKDescriptorPool(MVKDevice* device,
|
||||
const VkDescriptorPoolCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
|
||||
// MVKLogDebug("Pool %p created.", this);
|
||||
_maxSets = pCreateInfo->maxSets;
|
||||
_allocatedSetCount = 0;
|
||||
}
|
||||
|
||||
// TODO: Destroying a descriptor pool implicitly destroys all descriptor sets created from it.
|
||||
|
||||
MVKDescriptorPool::~MVKDescriptorPool() { reset(0); }
|
||||
MVKDescriptorPool::~MVKDescriptorPool() {
|
||||
// MVKLogDebug("Pool %p destroyed with %d descriptor sets.", this, _allocatedSetCount);
|
||||
reset(0);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
@ -72,20 +72,4 @@ namespace mvk {
|
||||
*/
|
||||
bool writeFile(const std::string& path, const std::vector<char>& contents, std::string& errMsg);
|
||||
|
||||
/**
|
||||
* Iterates through the directory at the specified path, which may be either a relative
|
||||
* or absolute path, and calls the processFile(std::string filePath) member function
|
||||
* on the fileProcessor for each file in the directory. If the isRecursive parameter
|
||||
* is true, the iteration will include all files in all sub-directories as well.
|
||||
* The processFile(std::string filePath) member function on the fileProcessor should
|
||||
* return true to cause the processing of any further files to halt, and this function
|
||||
* to return, or should return false to allow further files to be iterated.
|
||||
* Returns false if the directory could not be found or iterated. Returns true otherwise.
|
||||
*/
|
||||
template <typename FileProcessor>
|
||||
bool iterateDirectory(const std::string& dirPath,
|
||||
FileProcessor& fileProcessor,
|
||||
bool isRecursive,
|
||||
std::string& errMsg);
|
||||
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
*/
|
||||
|
||||
#include "FileSupport.h"
|
||||
#include "MoltenVKShaderConverterTool.h"
|
||||
#include <fstream>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@ -139,37 +138,3 @@ bool mvk::writeFile(const string& path, const vector<char>& contents, string& er
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename FileProcessor>
|
||||
bool mvk::iterateDirectory(const string& dirPath,
|
||||
FileProcessor& fileProcessor,
|
||||
bool isRecursive,
|
||||
string& errMsg) {
|
||||
NSString* nsAbsDirPath = @(absolutePath(dirPath).data());
|
||||
NSFileManager* fileMgr = NSFileManager.defaultManager;
|
||||
BOOL isDir = false;
|
||||
BOOL exists = [fileMgr fileExistsAtPath: nsAbsDirPath isDirectory: &isDir];
|
||||
if ( !exists ) {
|
||||
errMsg = "Could not locate directory: " + absolutePath(dirPath);
|
||||
return false;
|
||||
}
|
||||
if ( !isDir ) {
|
||||
errMsg = absolutePath(dirPath) + " is not a directory.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NSDirectoryEnumerator* dirEnum = [fileMgr enumeratorAtPath: nsAbsDirPath];
|
||||
NSString* filePath;
|
||||
while ((filePath = dirEnum.nextObject)) {
|
||||
if ( !isRecursive ) { [dirEnum skipDescendants]; }
|
||||
NSString* absFilePath = [nsAbsDirPath stringByAppendingPathComponent: filePath];
|
||||
if(fileProcessor.processFile(absFilePath.UTF8String)) { return true; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Concrete template implementation to allow MoltenVKShaderConverterTool to iterate the files in a directory. */
|
||||
template bool mvk::iterateDirectory<MoltenVKShaderConverterTool>(const string& dirPath,
|
||||
MoltenVKShaderConverterTool& fileProcessor,
|
||||
bool isRecursive,
|
||||
string& errMsg);
|
||||
|
@ -19,9 +19,11 @@
|
||||
#include "SPIRVToMSLConverter.h"
|
||||
#include "MVKCommonEnvironment.h"
|
||||
#include "MVKStrings.h"
|
||||
#include "FileSupport.h"
|
||||
#include "spirv_msl.hpp"
|
||||
#include "spirv_glsl.hpp"
|
||||
#include <spirv-tools/libspirv.h>
|
||||
#import <CoreFoundation/CFByteOrder.h>
|
||||
|
||||
using namespace mvk;
|
||||
using namespace std;
|
||||
@ -261,6 +263,27 @@ void SPIRVToMSLConverter::logSPIRV(const char* opDesc) {
|
||||
_resultLog += " SPIR-V:\n";
|
||||
_resultLog += spvLog;
|
||||
_resultLog += "\nEnd SPIR-V\n\n";
|
||||
|
||||
// Uncomment one or both of the following lines to get additional debugging and tracability capabilities.
|
||||
// The SPIR-V can be written in binary form to a file, and/or logged in human readable form to the console.
|
||||
// These can be helpful if errors occur during conversion of SPIR-V to MSL.
|
||||
// writeSPIRVToFile("spvout.spv");
|
||||
// printf("\n%s\n", getResultLog().c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the SPIR-V code to a file. This can be useful for debugging
|
||||
* when the SPRIR-V did not originally come from a known file
|
||||
*/
|
||||
void SPIRVToMSLConverter::writeSPIRVToFile(string spvFilepath) {
|
||||
vector<char> fileContents;
|
||||
spirvToBytes(_spirv, fileContents);
|
||||
string errMsg;
|
||||
if (writeFile(spvFilepath, fileContents, errMsg)) {
|
||||
_resultLog += "Saved SPIR-V to file: " + absolutePath(spvFilepath) + "\n\n";
|
||||
} else {
|
||||
_resultLog += "Could not write SPIR-V file. " + errMsg + "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
/** Validates that the SPIR-V code will disassemble during logging. */
|
||||
@ -323,4 +346,33 @@ MVK_PUBLIC_SYMBOL void mvk::logSPIRV(vector<uint32_t>& spirv, string& spvLog) {
|
||||
spvTextDestroy(text);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL void mvk::spirvToBytes(const vector<uint32_t>& spv, vector<char>& bytes) {
|
||||
// Assumes desired endianness.
|
||||
size_t byteCnt = spv.size() * sizeof(uint32_t);
|
||||
char* cBytes = (char*)spv.data();
|
||||
bytes.clear();
|
||||
bytes.insert(bytes.end(), cBytes, cBytes + byteCnt);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL void mvk::bytesToSPIRV(const vector<char>& bytes, vector<uint32_t>& spv) {
|
||||
size_t spvCnt = bytes.size() / sizeof(uint32_t);
|
||||
uint32_t* cSPV = (uint32_t*)bytes.data();
|
||||
spv.clear();
|
||||
spv.insert(spv.end(), cSPV, cSPV + spvCnt);
|
||||
ensureSPIRVEndianness(spv);
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL bool mvk::ensureSPIRVEndianness(vector<uint32_t>& spv) {
|
||||
if (spv.empty()) { return false; } // Nothing to convert
|
||||
|
||||
uint32_t magNum = spv.front();
|
||||
if (magNum == spv::MagicNumber) { return false; } // No need to convert
|
||||
|
||||
if (CFSwapInt32(magNum) == spv::MagicNumber) { // Yep, it's SPIR-V, but wrong endianness
|
||||
for (auto& elem : spv) { elem = CFSwapInt32(elem); }
|
||||
return true;
|
||||
}
|
||||
return false; // Not SPIR-V, so don't convert
|
||||
}
|
||||
|
||||
|
||||
|
@ -218,6 +218,7 @@ namespace mvk {
|
||||
bool logError(const char* errMsg);
|
||||
void logSPIRV(const char* opDesc);
|
||||
bool validateSPIRV();
|
||||
void writeSPIRVToFile(std::string spvFilepath);
|
||||
void logSource(std::string& src, const char* srcLang, const char* opDesc);
|
||||
|
||||
std::vector<uint32_t> _spirv;
|
||||
@ -233,5 +234,24 @@ namespace mvk {
|
||||
/** Appends the SPIR-V in human-readable form to the specified log string. */
|
||||
void logSPIRV(std::vector<uint32_t>& spirv, std::string& spvLog);
|
||||
|
||||
/** Converts the SPIR-V code to an array of bytes (suitable for writing to a file). */
|
||||
void spirvToBytes(const std::vector<uint32_t>& spv, std::vector<char>& bytes);
|
||||
|
||||
/** Converts an array of bytes (as read from a file) to SPIR-V code. */
|
||||
void bytesToSPIRV(const std::vector<char>& bytes, std::vector<uint32_t>& spv);
|
||||
|
||||
/**
|
||||
* Ensures that the specified SPIR-V code has the correct endianness for this system,
|
||||
* and converts it in place if necessary. This can be used after loading SPIR-V code
|
||||
* from a file that may have been encoded on a system with the opposite endianness.
|
||||
*
|
||||
* This function tests for the SPIR-V magic number (in both endian states) to determine
|
||||
* whether conversion is required. It will not convert arrays of uint32_t values that
|
||||
* are not SPIR-V code.
|
||||
*
|
||||
* Returns whether the endianness was changed.
|
||||
*/
|
||||
bool ensureSPIRVEndianness(std::vector<uint32_t>& spv);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -23,7 +23,6 @@
|
||||
A91425E41EF9542E00891AFD /* InitializeDll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A91425E11EF9542E00891AFD /* InitializeDll.cpp */; };
|
||||
A91425E51EF9542E00891AFD /* InitializeDll.h in Headers */ = {isa = PBXBuildFile; fileRef = A91425E21EF9542E00891AFD /* InitializeDll.h */; };
|
||||
A91425E61EF9542E00891AFD /* InitializeDll.h in Headers */ = {isa = PBXBuildFile; fileRef = A91425E21EF9542E00891AFD /* InitializeDll.h */; };
|
||||
A925B70C1C7754B2006E7ECD /* FileSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = A925B70A1C7754B2006E7ECD /* FileSupport.mm */; };
|
||||
A925B71A1C78DEB2006E7ECD /* MoltenVKGLSLToSPIRVConverter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A964BD601C57EFBD00D930D8 /* MoltenVKGLSLToSPIRVConverter.framework */; };
|
||||
A925B71B1C78DEB2006E7ECD /* MoltenVKSPIRVToMSLConverter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A93903C71C57E9ED00FE90DC /* MoltenVKSPIRVToMSLConverter.framework */; };
|
||||
A928C9191D0488DC00071B88 /* SPIRVConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = A928C9171D0488DC00071B88 /* SPIRVConversion.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -458,6 +457,9 @@
|
||||
A92C04471FF2A39A00BAAE59 /* validation_state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A92C029C1FF2A39A00BAAE59 /* validation_state.cpp */; };
|
||||
A92C04481FF2A39A00BAAE59 /* decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = A92C029D1FF2A39A00BAAE59 /* decoration.h */; };
|
||||
A92C04491FF2A39A00BAAE59 /* decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = A92C029D1FF2A39A00BAAE59 /* decoration.h */; };
|
||||
A95096BB2003D00300F10950 /* FileSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = A925B70A1C7754B2006E7ECD /* FileSupport.mm */; };
|
||||
A95096BC2003D00300F10950 /* FileSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = A925B70A1C7754B2006E7ECD /* FileSupport.mm */; };
|
||||
A95096BF2003D32400F10950 /* DirectorySupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = A95096BD2003D32400F10950 /* DirectorySupport.mm */; };
|
||||
A95C5F3F1DEA9070000D17B6 /* spirv_cfg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A95C5F3D1DEA9070000D17B6 /* spirv_cfg.cpp */; };
|
||||
A95C5F401DEA9070000D17B6 /* spirv_cfg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A95C5F3D1DEA9070000D17B6 /* spirv_cfg.cpp */; };
|
||||
A95C5F411DEA9070000D17B6 /* spirv_cfg.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A95C5F3E1DEA9070000D17B6 /* spirv_cfg.hpp */; };
|
||||
@ -912,6 +914,8 @@
|
||||
A92C029D1FF2A39A00BAAE59 /* decoration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = decoration.h; sourceTree = "<group>"; };
|
||||
A93903BF1C57E9D700FE90DC /* MoltenVKSPIRVToMSLConverter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MoltenVKSPIRVToMSLConverter.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A93903C71C57E9ED00FE90DC /* MoltenVKSPIRVToMSLConverter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MoltenVKSPIRVToMSLConverter.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
A95096BD2003D32400F10950 /* DirectorySupport.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DirectorySupport.mm; sourceTree = "<group>"; };
|
||||
A95096BE2003D32400F10950 /* DirectorySupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectorySupport.h; sourceTree = "<group>"; };
|
||||
A95C5F3D1DEA9070000D17B6 /* spirv_cfg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = spirv_cfg.cpp; path = "SPIRV-Cross/spirv_cfg.cpp"; sourceTree = "<group>"; };
|
||||
A95C5F3E1DEA9070000D17B6 /* spirv_cfg.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = spirv_cfg.hpp; path = "SPIRV-Cross/spirv_cfg.hpp"; sourceTree = "<group>"; };
|
||||
A964BD5F1C57EFBD00D930D8 /* MoltenVKShaderConverter */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MoltenVKShaderConverter; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@ -1037,6 +1041,8 @@
|
||||
children = (
|
||||
A9FE521B1D440E17001DD573 /* SPIRV-Tools */,
|
||||
A9381E5C1CB55F4600287A79 /* SPIRV-Cross */,
|
||||
A925B70B1C7754B2006E7ECD /* FileSupport.h */,
|
||||
A925B70A1C7754B2006E7ECD /* FileSupport.mm */,
|
||||
A928C9171D0488DC00071B88 /* SPIRVConversion.h */,
|
||||
A928C9181D0488DC00071B88 /* SPIRVConversion.mm */,
|
||||
A9093F5A1C58013E0094110D /* SPIRVToMSLConverter.cpp */,
|
||||
@ -1380,8 +1386,8 @@
|
||||
A97CC73C1C7527F3004A5C7E /* MoltenVKShaderConverterTool */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A925B70A1C7754B2006E7ECD /* FileSupport.mm */,
|
||||
A925B70B1C7754B2006E7ECD /* FileSupport.h */,
|
||||
A95096BE2003D32400F10950 /* DirectorySupport.h */,
|
||||
A95096BD2003D32400F10950 /* DirectorySupport.mm */,
|
||||
A97CC73D1C7527F3004A5C7E /* main.cpp */,
|
||||
A97CC73E1C7527F3004A5C7E /* MoltenVKShaderConverterTool.cpp */,
|
||||
A97CC73F1C7527F3004A5C7E /* MoltenVKShaderConverterTool.h */,
|
||||
@ -2089,7 +2095,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A97CC7411C7527F3004A5C7E /* MoltenVKShaderConverterTool.cpp in Sources */,
|
||||
A925B70C1C7754B2006E7ECD /* FileSupport.mm in Sources */,
|
||||
A95096BF2003D32400F10950 /* DirectorySupport.mm in Sources */,
|
||||
A97CC7401C7527F3004A5C7E /* main.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -2247,6 +2253,7 @@
|
||||
A92C038C1FF2A39A00BAAE59 /* ccp_pass.cpp in Sources */,
|
||||
A92C03061FF2A39A00BAAE59 /* parsed_operand.cpp in Sources */,
|
||||
A92C03681FF2A39A00BAAE59 /* remove_duplicates_pass.cpp in Sources */,
|
||||
A95096BB2003D00300F10950 /* FileSupport.mm in Sources */,
|
||||
A92C02DC1FF2A39A00BAAE59 /* spirv_validator_options.cpp in Sources */,
|
||||
A92C03741FF2A39A00BAAE59 /* type_manager.cpp in Sources */,
|
||||
A92C03161FF2A39A00BAAE59 /* software_version.cpp in Sources */,
|
||||
@ -2366,6 +2373,7 @@
|
||||
A92C038D1FF2A39A00BAAE59 /* ccp_pass.cpp in Sources */,
|
||||
A92C03071FF2A39A00BAAE59 /* parsed_operand.cpp in Sources */,
|
||||
A92C03691FF2A39A00BAAE59 /* remove_duplicates_pass.cpp in Sources */,
|
||||
A95096BC2003D00300F10950 /* FileSupport.mm in Sources */,
|
||||
A92C02DD1FF2A39A00BAAE59 /* spirv_validator_options.cpp in Sources */,
|
||||
A92C03751FF2A39A00BAAE59 /* type_manager.cpp in Sources */,
|
||||
A92C03171FF2A39A00BAAE59 /* software_version.cpp in Sources */,
|
||||
|
@ -77,7 +77,7 @@
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "/Users/bill/Documents/Dev/iOSProjects/Molten/MoltenVK-bh/External/SPIRV-Cross/shaders-msl/vert/dynamic.flatten.vert"
|
||||
argument = "/Users/bill/Documents/Dev/iOSProjects/Molten/MoltenVK-bh/External/SPIRV-Cross/shaders/flatten/rowmajor.flatten.vert"
|
||||
isEnabled = "NO">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
@ -85,7 +85,7 @@
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "/Users/bill/Documents/Dev/iOSProjects/Molten/dynamic.flatten.vert.spv"
|
||||
argument = "/Users/bill/Documents/Dev/iOSProjects/Molten/Support/Valve/Dota2/OpVectorShuffle_OOM.spv"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* DirectorySupport.h
|
||||
*
|
||||
* Copyright (c) 2014-2017 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace mvk {
|
||||
|
||||
/**
|
||||
* Iterates through the directory at the specified path, which may be either a relative
|
||||
* or absolute path, and calls the processFile(std::string filePath) member function
|
||||
* on the fileProcessor for each file in the directory. If the isRecursive parameter
|
||||
* is true, the iteration will include all files in all sub-directories as well.
|
||||
* The processFile(std::string filePath) member function on the fileProcessor should
|
||||
* return true to cause the processing of any further files to halt, and this function
|
||||
* to return, or should return false to allow further files to be iterated.
|
||||
* Returns false if the directory could not be found or iterated. Returns true otherwise.
|
||||
*/
|
||||
template <typename FileProcessor>
|
||||
bool iterateDirectory(const std::string& dirPath,
|
||||
FileProcessor& fileProcessor,
|
||||
bool isRecursive,
|
||||
std::string& errMsg);
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* DirectorySupport.mm
|
||||
*
|
||||
* Copyright (c) 2014-2017 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "DirectorySupport.h"
|
||||
#include "FileSupport.h"
|
||||
#include "MoltenVKShaderConverterTool.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace mvk;
|
||||
|
||||
template <typename FileProcessor>
|
||||
bool mvk::iterateDirectory(const string& dirPath,
|
||||
FileProcessor& fileProcessor,
|
||||
bool isRecursive,
|
||||
string& errMsg) {
|
||||
NSString* nsAbsDirPath = @(absolutePath(dirPath).data());
|
||||
NSFileManager* fileMgr = NSFileManager.defaultManager;
|
||||
BOOL isDir = false;
|
||||
BOOL exists = [fileMgr fileExistsAtPath: nsAbsDirPath isDirectory: &isDir];
|
||||
if ( !exists ) {
|
||||
errMsg = "Could not locate directory: " + absolutePath(dirPath);
|
||||
return false;
|
||||
}
|
||||
if ( !isDir ) {
|
||||
errMsg = absolutePath(dirPath) + " is not a directory.";
|
||||
return false;
|
||||
}
|
||||
|
||||
NSDirectoryEnumerator* dirEnum = [fileMgr enumeratorAtPath: nsAbsDirPath];
|
||||
NSString* filePath;
|
||||
while ((filePath = dirEnum.nextObject)) {
|
||||
if ( !isRecursive ) { [dirEnum skipDescendants]; }
|
||||
NSString* absFilePath = [nsAbsDirPath stringByAppendingPathComponent: filePath];
|
||||
if(fileProcessor.processFile(absFilePath.UTF8String)) { return true; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Concrete template implementation to allow MoltenVKShaderConverterTool to iterate the files in a directory. */
|
||||
template bool mvk::iterateDirectory<MoltenVKShaderConverterTool>(const string& dirPath,
|
||||
MoltenVKShaderConverterTool& fileProcessor,
|
||||
bool isRecursive,
|
||||
string& errMsg);
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
#include "MoltenVKShaderConverterTool.h"
|
||||
#include "FileSupport.h"
|
||||
#include "DirectorySupport.h"
|
||||
#include "GLSLToSPIRVConverter.h"
|
||||
#include "SPIRVToMSLConverter.h"
|
||||
#import <CoreFoundation/CFByteOrder.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace mvk;
|
||||
@ -526,33 +526,3 @@ bool mvk::equal(string const& a, string const& b, bool checkCase) {
|
||||
return checkCase ? (a == b) : (equal(b.begin(), b.end(), a.begin(), compareIgnoringCase));
|
||||
}
|
||||
|
||||
void mvk::spirvToBytes(const vector<uint32_t>& spv, vector<char>& bytes) {
|
||||
// Assumes desired endianness.
|
||||
size_t byteCnt = spv.size() * sizeof(uint32_t);
|
||||
char* cBytes = (char*)spv.data();
|
||||
bytes.clear();
|
||||
bytes.insert(bytes.end(), cBytes, cBytes + byteCnt);
|
||||
}
|
||||
|
||||
void mvk::bytesToSPIRV(const vector<char>& bytes, vector<uint32_t>& spv) {
|
||||
size_t spvCnt = bytes.size() / sizeof(uint32_t);
|
||||
uint32_t* cSPV = (uint32_t*)bytes.data();
|
||||
spv.clear();
|
||||
spv.insert(spv.end(), cSPV, cSPV + spvCnt);
|
||||
ensureSPIRVEndianness(spv);
|
||||
}
|
||||
|
||||
bool mvk::ensureSPIRVEndianness(vector<uint32_t>& spv) {
|
||||
if (spv.empty()) { return false; } // Nothing to convert
|
||||
|
||||
uint32_t magNum = spv.front();
|
||||
if (magNum == spv::MagicNumber) { return false; } // No need to convert
|
||||
|
||||
if (CFSwapInt32(magNum) == spv::MagicNumber) { // Yep, it's SPIR-V, but wrong endianness
|
||||
for (auto& elem : spv) { elem = CFSwapInt32(elem); }
|
||||
return true;
|
||||
}
|
||||
return false; // Not SPIR-V, so don't convert
|
||||
}
|
||||
|
||||
|
||||
|
@ -111,23 +111,4 @@ namespace mvk {
|
||||
/** Compares the specified strings, with or without sensitivity to case. */
|
||||
bool equal(std::string const& a, std::string const& b, bool checkCase = true);
|
||||
|
||||
/** Converts the SPIR-V code to an array of bytes (suitable for writing to a file). */
|
||||
void spirvToBytes(const std::vector<uint32_t>& spv, std::vector<char>& bytes);
|
||||
|
||||
/** Converts an array of bytes (as read from a file) to SPIR-V code. */
|
||||
void bytesToSPIRV(const std::vector<char>& bytes, std::vector<uint32_t>& spv);
|
||||
|
||||
/**
|
||||
* Ensures that the specified SPIR-V code has the correct endianness for this system,
|
||||
* and converts it in place if necessary. This can be used after loading SPIR-V code
|
||||
* from a file that may have been encoded on a system with the opposite endianness.
|
||||
*
|
||||
* This function tests for the SPIR-V magic number (in both endian states) to determine
|
||||
* whether conversion is required. It will not convert arrays of uint32_t values that
|
||||
* are not SPIR-V code.
|
||||
*
|
||||
* Returns whether the endianness was changed.
|
||||
*/
|
||||
bool ensureSPIRVEndianness(std::vector<uint32_t>& spv);
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user