Shader libraries cached in MVKPipelineCache instead of MVKShaderModule.
This commit is contained in:
parent
fd7521dc7b
commit
c45b47183e
@ -105,9 +105,11 @@ typedef struct {
|
|||||||
|
|
||||||
/** MoltenVK performance of shader compilation events for a VkDevice. */
|
/** MoltenVK performance of shader compilation events for a VkDevice. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
MVKShaderCompilationEventPerformance hashShaderCode; /** Create a hash from the incoming shader code. */
|
||||||
MVKShaderCompilationEventPerformance spirvToMSL; /** Convert SPIR-V to MSL source code. */
|
MVKShaderCompilationEventPerformance spirvToMSL; /** Convert SPIR-V to MSL source code. */
|
||||||
MVKShaderCompilationEventPerformance mslCompile; /** Compile MSL source code into a MTLLibrary. */
|
MVKShaderCompilationEventPerformance mslCompile; /** Compile MSL source code into a MTLLibrary. */
|
||||||
MVKShaderCompilationEventPerformance mslLoad; /** Load pre-compiled MSL code into a MTLLibrary. */
|
MVKShaderCompilationEventPerformance mslLoad; /** Load pre-compiled MSL code into a MTLLibrary. */
|
||||||
|
MVKShaderCompilationEventPerformance shaderLibraryFromCache; /** Retrieve a shader library from the cache, lazily creating it if needed. */
|
||||||
MVKShaderCompilationEventPerformance functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */
|
MVKShaderCompilationEventPerformance functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */
|
||||||
MVKShaderCompilationEventPerformance functionSpecialization; /** Specialize a retrieved MTLFunction. */
|
MVKShaderCompilationEventPerformance functionSpecialization; /** Specialize a retrieved MTLFunction. */
|
||||||
MVKShaderCompilationEventPerformance pipelineCompile; /** Compile MTLFunctions into a pipeline. */
|
MVKShaderCompilationEventPerformance pipelineCompile; /** Compile MTLFunctions into a pipeline. */
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include "MVKCmdQueries.h"
|
#include "MVKCmdQueries.h"
|
||||||
#include "MVKMTLBufferAllocation.h"
|
#include "MVKMTLBufferAllocation.h"
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <unordered_map>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ public:
|
|||||||
return (MVKPhysicalDevice*)getDispatchableObject(vkPhysicalDevice);
|
return (MVKPhysicalDevice*)getDispatchableObject(vkPhysicalDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
friend class MVKDevice;
|
friend class MVKDevice;
|
||||||
|
|
||||||
MTLFeatureSet getMaximalMTLFeatureSet();
|
MTLFeatureSet getMaximalMTLFeatureSet();
|
||||||
|
@ -1325,22 +1325,24 @@ void MVKDevice::addShaderCompilationEventPerformanceImpl(MVKShaderCompilationEve
|
|||||||
double currInterval = mvkGetElapsedMilliseconds(startTime, endTime);
|
double currInterval = mvkGetElapsedMilliseconds(startTime, endTime);
|
||||||
shaderCompilationEvent.minimumDuration = min(currInterval, shaderCompilationEvent.minimumDuration);
|
shaderCompilationEvent.minimumDuration = min(currInterval, shaderCompilationEvent.minimumDuration);
|
||||||
shaderCompilationEvent.maximumDuration = max(currInterval, shaderCompilationEvent.maximumDuration);
|
shaderCompilationEvent.maximumDuration = max(currInterval, shaderCompilationEvent.maximumDuration);
|
||||||
double totalInverval = (shaderCompilationEvent.averageDuration * shaderCompilationEvent.count++) + currInterval;
|
double totalInterval = (shaderCompilationEvent.averageDuration * shaderCompilationEvent.count++) + currInterval;
|
||||||
shaderCompilationEvent.averageDuration = totalInverval / shaderCompilationEvent.count;
|
shaderCompilationEvent.averageDuration = totalInterval / shaderCompilationEvent.count;
|
||||||
|
|
||||||
MVKLogInfo("%s performance curr: %.3f ms, avg: %.3f ms, min: %.3f ms, max: %.3f ms, count: %d",
|
MVKLogDebug("%s performance curr: %.3f ms, avg: %.3f ms, min: %.3f ms, max: %.3f ms, count: %d",
|
||||||
getShaderCompilationEventName(shaderCompilationEvent),
|
getShaderCompilationEventName(shaderCompilationEvent),
|
||||||
currInterval,
|
currInterval,
|
||||||
shaderCompilationEvent.averageDuration,
|
shaderCompilationEvent.averageDuration,
|
||||||
shaderCompilationEvent.minimumDuration,
|
shaderCompilationEvent.minimumDuration,
|
||||||
shaderCompilationEvent.maximumDuration,
|
shaderCompilationEvent.maximumDuration,
|
||||||
shaderCompilationEvent.count);
|
shaderCompilationEvent.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* MVKDevice::getShaderCompilationEventName(MVKShaderCompilationEventPerformance& shaderCompilationEvent) {
|
const char* MVKDevice::getShaderCompilationEventName(MVKShaderCompilationEventPerformance& shaderCompilationEvent) {
|
||||||
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.hashShaderCode) { return "Hash shader code"; }
|
||||||
if (&shaderCompilationEvent == &_shaderCompilationPerformance.spirvToMSL) { return "Convert SPIR-V to MSL source code"; }
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.spirvToMSL) { return "Convert SPIR-V to MSL source code"; }
|
||||||
if (&shaderCompilationEvent == &_shaderCompilationPerformance.mslCompile) { return "Compile MSL source code into a MTLLibrary"; }
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.mslCompile) { return "Compile MSL source code into a MTLLibrary"; }
|
||||||
if (&shaderCompilationEvent == &_shaderCompilationPerformance.mslLoad) { return "Load pre-compiled MSL code into a MTLLibrary"; }
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.mslLoad) { return "Load pre-compiled MSL code into a MTLLibrary"; }
|
||||||
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.shaderLibraryFromCache) { return "Retrieve shader library from the cache."; }
|
||||||
if (&shaderCompilationEvent == &_shaderCompilationPerformance.functionRetrieval) { return "Retrieve a MTLFunction from a MTLLibrary"; }
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.functionRetrieval) { return "Retrieve a MTLFunction from a MTLLibrary"; }
|
||||||
if (&shaderCompilationEvent == &_shaderCompilationPerformance.functionSpecialization) { return "Specialize a retrieved MTLFunction"; }
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.functionSpecialization) { return "Specialize a retrieved MTLFunction"; }
|
||||||
if (&shaderCompilationEvent == &_shaderCompilationPerformance.pipelineCompile) { return "Compile MTLFunctions into a pipeline"; }
|
if (&shaderCompilationEvent == &_shaderCompilationPerformance.pipelineCompile) { return "Compile MTLFunctions into a pipeline"; }
|
||||||
@ -1464,9 +1466,11 @@ void MVKDevice::initPerformanceTracking() {
|
|||||||
initPerf.minimumDuration = numeric_limits<double>::max();
|
initPerf.minimumDuration = numeric_limits<double>::max();
|
||||||
initPerf.maximumDuration = 0.0;
|
initPerf.maximumDuration = 0.0;
|
||||||
|
|
||||||
|
_shaderCompilationPerformance.hashShaderCode = initPerf;
|
||||||
_shaderCompilationPerformance.spirvToMSL = initPerf;
|
_shaderCompilationPerformance.spirvToMSL = initPerf;
|
||||||
_shaderCompilationPerformance.mslCompile = initPerf;
|
_shaderCompilationPerformance.mslCompile = initPerf;
|
||||||
_shaderCompilationPerformance.mslLoad = initPerf;
|
_shaderCompilationPerformance.mslLoad = initPerf;
|
||||||
|
_shaderCompilationPerformance.shaderLibraryFromCache = initPerf;
|
||||||
_shaderCompilationPerformance.functionRetrieval = initPerf;
|
_shaderCompilationPerformance.functionRetrieval = initPerf;
|
||||||
_shaderCompilationPerformance.functionSpecialization = initPerf;
|
_shaderCompilationPerformance.functionSpecialization = initPerf;
|
||||||
_shaderCompilationPerformance.pipelineCompile = initPerf;
|
_shaderCompilationPerformance.pipelineCompile = initPerf;
|
||||||
|
@ -71,7 +71,12 @@ public:
|
|||||||
virtual void encode(MVKCommandEncoder* cmdEncoder) = 0;
|
virtual void encode(MVKCommandEncoder* cmdEncoder) = 0;
|
||||||
|
|
||||||
/** Constructs an instance for the device. layout, and parent (which may be NULL). */
|
/** Constructs an instance for the device. layout, and parent (which may be NULL). */
|
||||||
MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipeline* parent) : MVKBaseDeviceObject(device) {}
|
MVKPipeline(MVKDevice* device, MVKPipelineCache* pipelineCache, MVKPipeline* parent) : MVKBaseDeviceObject(device),
|
||||||
|
_pipelineCache(pipelineCache) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MVKPipelineCache* _pipelineCache;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -168,6 +173,9 @@ public:
|
|||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return a shader library from the specified shader context sourced from the specified shader module. */
|
||||||
|
MVKShaderLibrary* getShaderLibrary(SPIRVToMSLConverterContext* pContext, MVKShaderModule* shaderModule);
|
||||||
|
|
||||||
/** Merges the contents of the specified number of pipeline caches into this cache. */
|
/** Merges the contents of the specified number of pipeline caches into this cache. */
|
||||||
inline VkResult mergePipelineCaches(uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) { return VK_SUCCESS; }
|
inline VkResult mergePipelineCaches(uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) { return VK_SUCCESS; }
|
||||||
|
|
||||||
@ -176,4 +184,10 @@ public:
|
|||||||
/** Constructs an instance for the specified device. */
|
/** Constructs an instance for the specified device. */
|
||||||
MVKPipelineCache(MVKDevice* device, const VkPipelineCacheCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {}
|
MVKPipelineCache(MVKDevice* device, const VkPipelineCacheCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {}
|
||||||
|
|
||||||
|
~MVKPipelineCache() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unordered_map<std::size_t, MVKShaderLibraryCache*> _shaderCacheByModuleHash;
|
||||||
|
std::mutex _shaderCacheLock;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -271,13 +271,13 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor
|
|||||||
// Vertex shader
|
// Vertex shader
|
||||||
if (mvkAreFlagsEnabled(pSS->stage, VK_SHADER_STAGE_VERTEX_BIT)) {
|
if (mvkAreFlagsEnabled(pSS->stage, VK_SHADER_STAGE_VERTEX_BIT)) {
|
||||||
shaderContext.options.entryPointStage = spv::ExecutionModelVertex;
|
shaderContext.options.entryPointStage = spv::ExecutionModelVertex;
|
||||||
plDesc.vertexFunction = mvkShdrMod->getMTLFunction(&shaderContext, pSS->pSpecializationInfo).mtlFunction;
|
plDesc.vertexFunction = mvkShdrMod->getMTLFunction(&shaderContext, pSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fragment shader
|
// Fragment shader
|
||||||
if (mvkAreFlagsEnabled(pSS->stage, VK_SHADER_STAGE_FRAGMENT_BIT)) {
|
if (mvkAreFlagsEnabled(pSS->stage, VK_SHADER_STAGE_FRAGMENT_BIT)) {
|
||||||
shaderContext.options.entryPointStage = spv::ExecutionModelFragment;
|
shaderContext.options.entryPointStage = spv::ExecutionModelFragment;
|
||||||
plDesc.fragmentFunction = mvkShdrMod->getMTLFunction(&shaderContext, pSS->pSpecializationInfo).mtlFunction;
|
plDesc.fragmentFunction = mvkShdrMod->getMTLFunction(&shaderContext, pSS->pSpecializationInfo, _pipelineCache).mtlFunction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,10 +437,36 @@ MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateI
|
|||||||
layout->populateShaderConverterContext(shaderContext);
|
layout->populateShaderConverterContext(shaderContext);
|
||||||
|
|
||||||
MVKShaderModule* mvkShdrMod = (MVKShaderModule*)pSS->module;
|
MVKShaderModule* mvkShdrMod = (MVKShaderModule*)pSS->module;
|
||||||
return mvkShdrMod->getMTLFunction(&shaderContext, pSS->pSpecializationInfo);
|
return mvkShdrMod->getMTLFunction(&shaderContext, pSS->pSpecializationInfo, _pipelineCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MVKComputePipeline::~MVKComputePipeline() {
|
MVKComputePipeline::~MVKComputePipeline() {
|
||||||
[_mtlPipelineState release];
|
[_mtlPipelineState release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKPipelineCache
|
||||||
|
|
||||||
|
/** Return a shader library from the specified shader context sourced from the specified shader module. */
|
||||||
|
MVKShaderLibrary* MVKPipelineCache::getShaderLibrary(SPIRVToMSLConverterContext* pContext, MVKShaderModule* shaderModule) {
|
||||||
|
lock_guard<mutex> lock(_shaderCacheLock);
|
||||||
|
|
||||||
|
size_t smKey = shaderModule->getKey();
|
||||||
|
MVKShaderLibraryCache* slCache = _shaderCacheByModuleHash[smKey];
|
||||||
|
if ( !slCache ) {
|
||||||
|
slCache = new MVKShaderLibraryCache(_device);
|
||||||
|
_shaderCacheByModuleHash[smKey] = slCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
return slCache->getShaderLibrary(pContext, shaderModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MVKPipelineCache::~MVKPipelineCache() {
|
||||||
|
for (auto& pair : _shaderCacheByModuleHash) { delete pair.second; }
|
||||||
|
_shaderCacheByModuleHash.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
|
class MVKPipelineCache;
|
||||||
|
|
||||||
using namespace mvk;
|
using namespace mvk;
|
||||||
|
|
||||||
|
|
||||||
@ -47,8 +49,8 @@ public:
|
|||||||
/** Returns the Metal shader function, possibly specialized. */
|
/** Returns the Metal shader function, possibly specialized. */
|
||||||
MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo);
|
MVKMTLFunction getMTLFunction(const VkSpecializationInfo* pSpecializationInfo);
|
||||||
|
|
||||||
/** Constructs an instance from the MSL source code in the specified SPIRVToMSLConverter. */
|
/** Constructs an instance from the specified MSL source code. */
|
||||||
MVKShaderLibrary(MVKDevice* device, SPIRVToMSLConverter& mslConverter);
|
MVKShaderLibrary(MVKDevice* device, const char* mslSourceCode, const SPIRVEntryPoint& entryPoint);
|
||||||
|
|
||||||
/** Constructs an instance from the specified compiled MSL code data. */
|
/** Constructs an instance from the specified compiled MSL code data. */
|
||||||
MVKShaderLibrary(MVKDevice* device,
|
MVKShaderLibrary(MVKDevice* device,
|
||||||
@ -66,6 +68,33 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark MVKShaderLibraryCache
|
||||||
|
|
||||||
|
/** Represents a cache of shader libraries for one shader module. */
|
||||||
|
class MVKShaderLibraryCache : public MVKBaseDeviceObject {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Return a shader library from the specified shader context sourced from the specified shader module. */
|
||||||
|
MVKShaderLibrary* getShaderLibrary(SPIRVToMSLConverterContext* pContext, MVKShaderModule* shaderModule);
|
||||||
|
|
||||||
|
MVKShaderLibraryCache(MVKDevice* device) : MVKBaseDeviceObject(device) {};
|
||||||
|
|
||||||
|
~MVKShaderLibraryCache() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MVKShaderLibrary* findShaderLibrary(SPIRVToMSLConverterContext* pContext);
|
||||||
|
MVKShaderLibrary* addShaderLibrary(SPIRVToMSLConverterContext* pContext,
|
||||||
|
const char* mslSourceCode,
|
||||||
|
const SPIRVEntryPoint& entryPoint);
|
||||||
|
|
||||||
|
std::mutex _accessLock;
|
||||||
|
std::size_t _shaderModuleHash;
|
||||||
|
std::vector<std::pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>> _shaderLibraries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKShaderModule
|
#pragma mark MVKShaderModule
|
||||||
|
|
||||||
@ -75,19 +104,32 @@ class MVKShaderModule : public MVKBaseDeviceObject {
|
|||||||
public:
|
public:
|
||||||
/** Returns the Metal shader function, possibly specialized. */
|
/** Returns the Metal shader function, possibly specialized. */
|
||||||
MVKMTLFunction getMTLFunction(SPIRVToMSLConverterContext* pContext,
|
MVKMTLFunction getMTLFunction(SPIRVToMSLConverterContext* pContext,
|
||||||
const VkSpecializationInfo* pSpecializationInfo);
|
const VkSpecializationInfo* pSpecializationInfo,
|
||||||
|
MVKPipelineCache* pipelineCache);
|
||||||
|
|
||||||
|
/** Convert the SPIR-V to MSL, using the specified shader conversion context. */
|
||||||
|
bool convert(SPIRVToMSLConverterContext* pContext);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Metal Shading Language source code most recently converted
|
||||||
|
* by the convert() function, or set directly using the setMSL() function.
|
||||||
|
*/
|
||||||
|
inline const std::string& getMSL() { return _converter.getMSL(); }
|
||||||
|
|
||||||
|
/** Returns information about the shader entry point. */
|
||||||
|
inline const SPIRVEntryPoint& getEntryPoint() { return _converter.getEntryPoint(); }
|
||||||
|
|
||||||
|
/** Returns a key as a means of identifying this shader module in a pipeline cache. */
|
||||||
|
inline std::size_t getKey() { return _key; }
|
||||||
|
|
||||||
MVKShaderModule(MVKDevice* device, const VkShaderModuleCreateInfo* pCreateInfo);
|
MVKShaderModule(MVKDevice* device, const VkShaderModuleCreateInfo* pCreateInfo);
|
||||||
|
|
||||||
~MVKShaderModule() override;
|
~MVKShaderModule() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MVKShaderLibrary* getShaderLibrary(SPIRVToMSLConverterContext* pContext);
|
MVKShaderLibraryCache _shaderLibraryCache;
|
||||||
MVKShaderLibrary* findShaderLibrary(SPIRVToMSLConverterContext* pContext);
|
|
||||||
MVKShaderLibrary* addShaderLibrary(SPIRVToMSLConverterContext* pContext);
|
|
||||||
|
|
||||||
SPIRVToMSLConverter _converter;
|
SPIRVToMSLConverter _converter;
|
||||||
MVKShaderLibrary* _defaultLibrary;
|
MVKShaderLibrary* _defaultLibrary;
|
||||||
std::vector<std::pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>> _shaderLibraries;
|
std::size_t _key;
|
||||||
std::mutex _accessLock;
|
std::mutex _accessLock;
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MVKShaderModule.h"
|
#include "MVKShaderModule.h"
|
||||||
|
#include "MVKPipeline.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
#include "vk_mvk_moltenvk.h"
|
#include "vk_mvk_moltenvk.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -119,19 +120,19 @@ MTLFunctionConstant* MVKShaderLibrary::getFunctionConstant(NSArray<MTLFunctionCo
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device, SPIRVToMSLConverter& mslConverter) : MVKBaseDeviceObject(device) {
|
MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device, const char* mslSourceCode, const SPIRVEntryPoint& entryPoint) : MVKBaseDeviceObject(device) {
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
MTLCompileOptions* options = [[MTLCompileOptions new] autorelease]; // TODO: what compile options apply?
|
MTLCompileOptions* options = [[MTLCompileOptions new] autorelease]; // TODO: what compile options apply?
|
||||||
NSError* err = nil;
|
NSError* err = nil;
|
||||||
_mtlLibrary = [getMTLDevice() newLibraryWithSource: @(mslConverter.getMSL().data())
|
_mtlLibrary = [getMTLDevice() newLibraryWithSource: @(mslSourceCode)
|
||||||
options: options
|
options: options
|
||||||
error: &err]; // retained
|
error: &err]; // retained
|
||||||
handleCompilationError(err, "Shader module compilation");
|
handleCompilationError(err, "Shader module compilation");
|
||||||
}
|
}
|
||||||
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.mslCompile, startTime);
|
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.mslCompile, startTime);
|
||||||
|
|
||||||
_entryPoint = mslConverter.getEntryPoint();
|
_entryPoint = entryPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device,
|
MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device,
|
||||||
@ -174,97 +175,150 @@ MVKShaderLibrary::~MVKShaderLibrary() {
|
|||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark MVKShaderModule
|
#pragma mark MVKShaderLibraryCache
|
||||||
|
|
||||||
MVKMTLFunction MVKShaderModule::getMTLFunction(SPIRVToMSLConverterContext* pContext,
|
|
||||||
const VkSpecializationInfo* pSpecializationInfo) {
|
|
||||||
lock_guard<mutex> lock(_accessLock);
|
|
||||||
MVKShaderLibrary* mvkLib = getShaderLibrary(pContext);
|
|
||||||
return mvkLib ? mvkLib->getMTLFunction(pSpecializationInfo) : MVKMTLFunctionNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
MVKShaderLibrary* MVKShaderModule::getShaderLibrary(SPIRVToMSLConverterContext* pContext) {
|
|
||||||
if (_defaultLibrary) { return _defaultLibrary; }
|
|
||||||
|
|
||||||
|
MVKShaderLibrary* MVKShaderLibraryCache::getShaderLibrary(SPIRVToMSLConverterContext* pContext,
|
||||||
|
MVKShaderModule* shaderModule) {
|
||||||
MVKShaderLibrary* shLib = findShaderLibrary(pContext);
|
MVKShaderLibrary* shLib = findShaderLibrary(pContext);
|
||||||
if ( !shLib ) { shLib = addShaderLibrary(pContext); }
|
if ( !shLib ) {
|
||||||
// else { MVKLogDebug("Shader Module %p reusing library.", this); }
|
if (shaderModule->convert(pContext)) {
|
||||||
|
shLib = addShaderLibrary(pContext, shaderModule->getMSL().c_str(), shaderModule->getEntryPoint());
|
||||||
|
}
|
||||||
|
}
|
||||||
return shLib;
|
return shLib;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds and returns a shader library matching the specified context, or returns nullptr if it doesn't exist.
|
// Finds and returns a shader library matching the specified context, or returns nullptr if it doesn't exist.
|
||||||
// If a match is found, the usage of the specified context is aligned with the context of the matching library.
|
// If a match is found, the usage of the specified context is aligned with the context of the matching library.
|
||||||
MVKShaderLibrary* MVKShaderModule::findShaderLibrary(SPIRVToMSLConverterContext* pContext) {
|
MVKShaderLibrary* MVKShaderLibraryCache::findShaderLibrary(SPIRVToMSLConverterContext* pContext) {
|
||||||
for (auto& slPair : _shaderLibraries) {
|
for (auto& slPair : _shaderLibraries) {
|
||||||
if (slPair.first.matches(*pContext)) {
|
if (slPair.first.matches(*pContext)) {
|
||||||
pContext->alignUsageWith(slPair.first);
|
pContext->alignUsageWith(slPair.first);
|
||||||
return slPair.second;
|
return slPair.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds and returns a new shader library configured from the specified context. */
|
/** Adds and returns a new shader library configured from the specified context. */
|
||||||
MVKShaderLibrary* MVKShaderModule::addShaderLibrary(SPIRVToMSLConverterContext* pContext) {
|
MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(SPIRVToMSLConverterContext* pContext,
|
||||||
|
const char* mslSourceCode,
|
||||||
|
const SPIRVEntryPoint& entryPoint) {
|
||||||
|
MVKShaderLibrary* shLib = new MVKShaderLibrary(_device, mslSourceCode, entryPoint);
|
||||||
|
_shaderLibraries.push_back(pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>(*pContext, shLib));
|
||||||
|
return shLib;
|
||||||
|
}
|
||||||
|
|
||||||
MVKShaderLibrary* shLib = nullptr;
|
MVKShaderLibraryCache::~MVKShaderLibraryCache() {
|
||||||
bool shouldLogCode = _device->_mvkConfig.debugMode;
|
for (auto& slPair : _shaderLibraries) { delete slPair.second; }
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t startTime = _device->getPerformanceTimestamp();
|
|
||||||
bool wasConverted = _converter.convert(*pContext, shouldLogCode, shouldLogCode, shouldLogCode);
|
|
||||||
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.spirvToMSL, startTime);
|
|
||||||
|
|
||||||
if (wasConverted) {
|
#pragma mark -
|
||||||
if (shouldLogCode) { MVKLogInfo("%s", _converter.getResultLog().data()); }
|
#pragma mark MVKShaderModule
|
||||||
shLib = new MVKShaderLibrary(_device, _converter);
|
|
||||||
_shaderLibraries.push_back(pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>(*pContext, shLib));
|
MVKMTLFunction MVKShaderModule::getMTLFunction(SPIRVToMSLConverterContext* pContext,
|
||||||
// MVKLogDebug("Shader Module %p compiled %d libraries.", this, _shaderLibraries.size());
|
const VkSpecializationInfo* pSpecializationInfo,
|
||||||
} else {
|
MVKPipelineCache* pipelineCache) {
|
||||||
mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "Unable to convert SPIR-V to MSL:\n%s", _converter.getResultLog().data());
|
lock_guard<mutex> lock(_accessLock);
|
||||||
}
|
MVKShaderLibrary* mvkLib = _defaultLibrary;
|
||||||
return shLib;
|
if ( !mvkLib ) {
|
||||||
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
|
if (pipelineCache) {
|
||||||
|
MVKLogDebug("Retrieving shader from pipeline cache.");
|
||||||
|
mvkLib = pipelineCache->getShaderLibrary(pContext, this);
|
||||||
|
} else {
|
||||||
|
MVKLogDebug("Retrieving shader from shader module.");
|
||||||
|
mvkLib = _shaderLibraryCache.getShaderLibrary(pContext, this);
|
||||||
|
}
|
||||||
|
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.shaderLibraryFromCache, startTime);
|
||||||
|
}
|
||||||
|
return mvkLib ? mvkLib->getMTLFunction(pSpecializationInfo) : MVKMTLFunctionNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MVKShaderModule::convert(SPIRVToMSLConverterContext* pContext) {
|
||||||
|
bool shouldLogCode = _device->_mvkConfig.debugMode;
|
||||||
|
|
||||||
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
|
bool wasConverted = _converter.convert(*pContext, shouldLogCode, shouldLogCode, shouldLogCode);
|
||||||
|
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.spirvToMSL, startTime);
|
||||||
|
|
||||||
|
if (wasConverted) {
|
||||||
|
if (shouldLogCode) { MVKLogInfo("%s", _converter.getResultLog().data()); }
|
||||||
|
} else {
|
||||||
|
mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "Unable to convert SPIR-V to MSL:\n%s", _converter.getResultLog().data());
|
||||||
|
}
|
||||||
|
return wasConverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark Construction
|
#pragma mark Construction
|
||||||
|
|
||||||
MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
MVKShaderModule::MVKShaderModule(MVKDevice* device,
|
||||||
const VkShaderModuleCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
|
const VkShaderModuleCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device),
|
||||||
|
_shaderLibraryCache(device) {
|
||||||
_defaultLibrary = nullptr;
|
_defaultLibrary = nullptr;
|
||||||
|
|
||||||
// Ensure something is there.
|
size_t codeSize = pCreateInfo->codeSize;
|
||||||
if ( (pCreateInfo->pCode != VK_NULL_HANDLE) && (pCreateInfo->codeSize >= 4) ) {
|
|
||||||
|
|
||||||
// Retrieve the magic number to determine what type of shader code has been loaded.
|
// Ensure something is there.
|
||||||
uint32_t magicNum = *pCreateInfo->pCode;
|
if ( (pCreateInfo->pCode == VK_NULL_HANDLE) || (codeSize < 4) ) {
|
||||||
switch (magicNum) {
|
setConfigurationResult(mvkNotifyErrorWithText(VK_INCOMPLETE, "Shader module contains no SPIR-V code."));
|
||||||
case kMVKMagicNumberSPIRVCode: { // SPIR-V code
|
return;
|
||||||
size_t spvCount = (pCreateInfo->codeSize + 3) >> 2; // Round up if byte length not exactly on uint32_t boundary
|
}
|
||||||
_converter.setSPIRV(pCreateInfo->pCode, spvCount);
|
|
||||||
break;
|
_key = mvkHash(&pCreateInfo->codeSize, 1);
|
||||||
}
|
|
||||||
case kMVKMagicNumberMSLSourceCode: { // MSL source code
|
// Retrieve the magic number to determine what type of shader code has been loaded.
|
||||||
uintptr_t pMSLCode = uintptr_t(pCreateInfo->pCode) + sizeof(MVKMSLSPIRVHeader);
|
uint32_t magicNum = *pCreateInfo->pCode;
|
||||||
_converter.setMSL((char*)pMSLCode, nullptr);
|
switch (magicNum) {
|
||||||
_defaultLibrary = new MVKShaderLibrary(_device, _converter);
|
case kMVKMagicNumberSPIRVCode: { // SPIR-V code
|
||||||
break;
|
size_t spvCount = (pCreateInfo->codeSize + 3) >> 2; // Round up if byte length not exactly on uint32_t boundary
|
||||||
}
|
|
||||||
case kMVKMagicNumberMSLCompiledCode: { // MSL compiled binary code
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
uintptr_t pMSLCode = uintptr_t(pCreateInfo->pCode) + sizeof(MVKMSLSPIRVHeader);
|
_key = mvkHash(pCreateInfo->pCode, spvCount, _key);
|
||||||
_defaultLibrary = new MVKShaderLibrary(_device, (void*)(pMSLCode), (pCreateInfo->codeSize - sizeof(MVKMSLSPIRVHeader)));
|
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);
|
||||||
break;
|
|
||||||
}
|
_converter.setSPIRV(pCreateInfo->pCode, spvCount);
|
||||||
default:
|
|
||||||
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "SPIR-V contains invalid magic number %x.", magicNum));
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case kMVKMagicNumberMSLSourceCode: { // MSL source code
|
||||||
} else {
|
size_t hdrSize = sizeof(MVKMSLSPIRVHeader);
|
||||||
setConfigurationResult(mvkNotifyErrorWithText(VK_INCOMPLETE, "Shader module contains no SPIR-V code."));
|
char* pMSLCode = (char*)(uintptr_t(pCreateInfo->pCode) + hdrSize);
|
||||||
}
|
size_t mslCodeLen = pCreateInfo->codeSize - hdrSize;
|
||||||
|
|
||||||
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
|
_key = mvkHash(&magicNum, 1, _key);
|
||||||
|
_key = mvkHash(pMSLCode, mslCodeLen, _key);
|
||||||
|
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);
|
||||||
|
|
||||||
|
_converter.setMSL(pMSLCode, nullptr);
|
||||||
|
_defaultLibrary = new MVKShaderLibrary(_device, _converter.getMSL().c_str(), _converter.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;
|
||||||
|
|
||||||
|
uint64_t startTime = _device->getPerformanceTimestamp();
|
||||||
|
_key = mvkHash(&magicNum, 1, _key);
|
||||||
|
_key = mvkHash(pMSLCode, mslCodeLen, _key);
|
||||||
|
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);
|
||||||
|
|
||||||
|
_defaultLibrary = new MVKShaderLibrary(_device, (void*)(pMSLCode), mslCodeLen);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FORMAT_NOT_SUPPORTED, "SPIR-V contains invalid magic number %x.", magicNum));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MVKShaderModule::~MVKShaderModule() {
|
MVKShaderModule::~MVKShaderModule() {
|
||||||
if (_defaultLibrary) { delete _defaultLibrary; }
|
if (_defaultLibrary) { delete _defaultLibrary; }
|
||||||
for (auto& slPair : _shaderLibraries) { delete slPair.second; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,10 +21,8 @@
|
|||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mach/mach.h>
|
|
||||||
#include <mach/mach_host.h>
|
#include <mach/mach_host.h>
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
#include <uuid/uuid.h>
|
|
||||||
|
|
||||||
#if MVK_MACOS
|
#if MVK_MACOS
|
||||||
#import <CoreFoundation/CFData.h>
|
#import <CoreFoundation/CFData.h>
|
||||||
|
@ -207,9 +207,6 @@ namespace mvk {
|
|||||||
/** Returns information about the shader entry point. */
|
/** Returns information about the shader entry point. */
|
||||||
const SPIRVEntryPoint& getEntryPoint() { return _entryPoint; }
|
const SPIRVEntryPoint& getEntryPoint() { return _entryPoint; }
|
||||||
|
|
||||||
/** Returns a mapping of entry point info, indexed by SPIR-V entry point name. */
|
|
||||||
// const SPIRVEntryPointsByName& getEntryPoints() { return _entryPoints; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the most recent conversion was successful.
|
* Returns whether the most recent conversion was successful.
|
||||||
*
|
*
|
||||||
@ -228,10 +225,6 @@ namespace mvk {
|
|||||||
_msl = msl;
|
_msl = msl;
|
||||||
if (pEntryPoint) { _entryPoint = *pEntryPoint; }
|
if (pEntryPoint) { _entryPoint = *pEntryPoint; }
|
||||||
}
|
}
|
||||||
// void setMSL(const std::string& msl, const SPIRVEntryPointsByName& entryPoints) {
|
|
||||||
// _msl = msl;
|
|
||||||
// _entryPoints = entryPoints;
|
|
||||||
// }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void logMsg(const char* logMsg);
|
void logMsg(const char* logMsg);
|
||||||
@ -245,7 +238,6 @@ namespace mvk {
|
|||||||
std::string _msl;
|
std::string _msl;
|
||||||
std::string _resultLog;
|
std::string _resultLog;
|
||||||
SPIRVEntryPoint _entryPoint;
|
SPIRVEntryPoint _entryPoint;
|
||||||
// SPIRVEntryPointsByName _entryPoints;
|
|
||||||
bool _wasConverted = false;
|
bool _wasConverted = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user