Merge pull request #8 from billhollings/master

SPIR-V enhancements.
This commit is contained in:
Bill Hollings 2018-01-08 22:40:49 -05:00 committed by GitHub
commit 8e6d9e62f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 215 additions and 135 deletions

View File

@ -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:
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.
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.
<a name="add_spirv-cross"></a>

@ -1 +1 @@
Subproject commit 95910ddd5aa03cbd7188fc7c107f9cc893136f10
Subproject commit 27d4af75a0736849c046c5f068ecc80f17c1ed7e

View File

@ -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 -

View File

@ -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);
}

View File

@ -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);

View File

@ -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
}

View File

@ -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

View File

@ -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 */,

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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
}

View File

@ -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);
}