Merge pull request #150 from billhollings/master

Fixes to run Vulkan CTS without crashes
This commit is contained in:
Bill Hollings 2018-05-08 12:35:50 -04:00 committed by GitHub
commit bbe5370f62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 280 additions and 212 deletions

View File

@ -48,7 +48,7 @@ extern "C" {
*/
#define MVK_VERSION_MAJOR 1
#define MVK_VERSION_MINOR 0
#define MVK_VERSION_PATCH 5
#define MVK_VERSION_PATCH 6
#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
@ -64,7 +64,7 @@ typedef struct {
VkBool32 supportLargeQueryPools; /**< Metal allows only 8192 occlusion queries per MTLBuffer. If enabled, MoltenVK allocates a MTLBuffer for each query pool, allowing each query pool to support 8192 queries, which may slow performance or cause unexpected behaviour if the query pool is not established prior to a Metal renderpass, or if the query pool is changed within a Metal renderpass. If disabled, one MTLBuffer will be shared by all query pools, which improves performance, but limits the total device queries to 8192. Default is false. */
VkBool32 presentWithCommandBuffer; /**< If enabled, each surface presentation is scheduled using a command buffer. Enabling this may improve rendering frame synchronization, but may result in reduced frame rates. Default value is false if the MVK_PRESENT_WITHOUT_COMMAND_BUFFER build setting is defined when MoltenVK is compiled, and true otherwise. By default the MVK_PRESENT_WITHOUT_COMMAND_BUFFER build setting is not defined and the value of this setting is true. */
VkBool32 displayWatermark; /**< If enabled, a MoltenVK logo watermark will be rendered on top of the scene. This can be enabled for publicity during demos. Default value is true if the MVK_DISPLAY_WATERMARK build setting is defined when MoltenVK is compiled, and false otherwise. By default the MVK_DISPLAY_WATERMARK build setting is not defined. */
VkBool32 performanceTracking; /**< If enabled, per-frame performance statistics are tracked, optionally logged, and can be retrieved via the vkGetSwapchainPerformanceMVK() function, and various shader compilation performance statistics are tracked, logged, and can be retrieved via the vkGetShaderCompilationPerformanceMVK() function. Default is false. */
VkBool32 performanceTracking; /**< If enabled, per-frame performance statistics are tracked, optionally logged, and can be retrieved via the vkGetSwapchainPerformanceMVK() function, and various performance statistics are tracked, logged, and can be retrieved via the vkGetPerformanceStatisticsMVK() function. Default is false. */
uint32_t performanceLoggingFrameCount; /**< If non-zero, performance statistics will be periodically logged to the console, on a repeating cycle of this many frames per swapchain. The performanceTracking capability must also be enabled. Default is zero, indicating no logging. */
} MVKDeviceConfiguration;
@ -96,30 +96,47 @@ typedef struct {
double averageFramesPerSecond; /**< The rolling average number of frames per second. This is simply the 1000 divided by the averageFrameInterval value. */
} MVKSwapchainPerformance;
/** MoltenVK performance of a particular type of shader compilation event. */
/** MoltenVK performance of a particular type of activity. */
typedef struct {
uint32_t count; /**< The number of compilation events of this type. */
double averageDuration; /**< The average duration of the compilation event, in milliseconds. */
double minimumDuration; /**< The minimum duration of the compilation event, in milliseconds. */
double maximumDuration; /**< The maximum duration of the compilation event, in milliseconds. */
} MVKShaderCompilationEventPerformance;
uint32_t count; /**< The number of activities of this type. */
double averageDuration; /**< The average duration of the activity, in milliseconds. */
double minimumDuration; /**< The minimum duration of the activity, in milliseconds. */
double maximumDuration; /**< The maximum duration of the activity, in milliseconds. */
} MVKPerformanceTracker;
/** MoltenVK performance of shader compilation events for a VkDevice. */
/** MoltenVK performance of shader compilation activities. */
typedef struct {
MVKShaderCompilationEventPerformance hashShaderCode; /** Create a hash from the incoming shader code. */
MVKShaderCompilationEventPerformance spirvToMSL; /** Convert SPIR-V to MSL source code. */
MVKShaderCompilationEventPerformance mslCompile; /** Compile MSL source 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 functionSpecialization; /** Specialize a retrieved MTLFunction. */
MVKShaderCompilationEventPerformance pipelineCompile; /** Compile MTLFunctions into a pipeline. */
MVKShaderCompilationEventPerformance sizePipelineCache; /** Calculate the size of cache data required to write MSL to pipeline cache data stream. */
MVKShaderCompilationEventPerformance writePipelineCache; /** Write MSL to pipeline cache data stream. */
MVKShaderCompilationEventPerformance readPipelineCache; /** Read MSL from pipeline cache data stream. */
MVKPerformanceTracker hashShaderCode; /** Create a hash from the incoming shader code. */
MVKPerformanceTracker spirvToMSL; /** Convert SPIR-V to MSL source code. */
MVKPerformanceTracker mslCompile; /** Compile MSL source code into a MTLLibrary. */
MVKPerformanceTracker mslLoad; /** Load pre-compiled MSL code into a MTLLibrary. */
MVKPerformanceTracker shaderLibraryFromCache; /** Retrieve a shader library from the cache, lazily creating it if needed. */
MVKPerformanceTracker functionRetrieval; /** Retrieve a MTLFunction from a MTLLibrary. */
MVKPerformanceTracker functionSpecialization; /** Specialize a retrieved MTLFunction. */
MVKPerformanceTracker pipelineCompile; /** Compile MTLFunctions into a pipeline. */
} MVKShaderCompilationPerformance;
/** MoltenVK performance of pipeline cache activities. */
typedef struct {
MVKPerformanceTracker sizePipelineCache; /** Calculate the size of cache data required to write MSL to pipeline cache data stream. */
MVKPerformanceTracker writePipelineCache; /** Write MSL to pipeline cache data stream. */
MVKPerformanceTracker readPipelineCache; /** Read MSL from pipeline cache data stream. */
} MVKPipelineCachePerformance;
/** MoltenVK performance of queue activities. */
typedef struct {
MVKPerformanceTracker mtlQueueAccess; /** Create an MTLCommmandQueue or access an existing cached instance. */
} MVKQueuePerformance;
/** MoltenVK performance. */
typedef struct {
MVKShaderCompilationPerformance shaderCompilation; /** Shader compilations activities. */
MVKPipelineCachePerformance pipelineCache; /** Pipeline cache activities. */
MVKQueuePerformance queue; /** Queue activities. */
} MVKPerformanceStatistics;
#pragma mark -
#pragma mark Function types
@ -127,7 +144,7 @@ typedef void (VKAPI_PTR *PFN_vkGetMoltenVKDeviceConfigurationMVK)(VkDevice devic
typedef VkResult (VKAPI_PTR *PFN_vkSetMoltenVKDeviceConfigurationMVK)(VkDevice device, MVKDeviceConfiguration* pConfiguration);
typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMetalFeaturesMVK)(VkPhysicalDevice physicalDevice, MVKPhysicalDeviceMetalFeatures* pMetalFeatures);
typedef void (VKAPI_PTR *PFN_vkGetSwapchainPerformanceMVK)(VkDevice device, VkSwapchainKHR swapchain, MVKSwapchainPerformance* pSwapchainPerf);
typedef void (VKAPI_PTR *PFN_vkGetShaderCompilationPerformanceMVK)(VkDevice device, MVKShaderCompilationPerformance* pShaderCompPerf);
typedef void (VKAPI_PTR *PFN_vkGetPerformanceStatisticsMVK)(VkDevice device, MVKPerformanceStatistics* pPerf);
typedef void (VKAPI_PTR *PFN_vkGetVersionStringsMVK)(char* pMoltenVersionStringBuffer, uint32_t moltenVersionStringBufferLength, char* pVulkanVersionStringBuffer, uint32_t vulkanVersionStringBufferLength);
#ifdef __OBJC__
@ -190,12 +207,12 @@ VKAPI_ATTR void VKAPI_CALL vkGetSwapchainPerformanceMVK(
MVKSwapchainPerformance* pSwapchainPerf);
/**
* Populates the specified MVKShaderCompilationPerformance structure with the
* current shader compilation performance statistics for the specified device.
* Populates the specified MVKPerformanceStatistics structure with
* the current performance statistics for the specified device.
*/
VKAPI_ATTR void VKAPI_CALL vkGetShaderCompilationPerformanceMVK(
VKAPI_ATTR void VKAPI_CALL vkGetPerformanceStatisticsMVK(
VkDevice device,
MVKShaderCompilationPerformance* pShaderCompPerf);
MVKPerformanceStatistics* pPerf);
/**
* Returns a human readable version of the MoltenVK and Vulkan versions.

View File

@ -146,7 +146,7 @@ void MVKCommandEncodingPool::initTextureDeviceMemory() {
}
MVKCommandEncodingPool::~MVKCommandEncodingPool() {
if (_transferImageMemory) { delete _transferImageMemory; }
if (_transferImageMemory) { _transferImageMemory->destroy(); }
destroyMetalResources();
}
@ -161,7 +161,7 @@ void MVKCommandEncodingPool::destroyMetalResources() {
for (auto& pair : _mtlDepthStencilStates) { [pair.second release]; }
_mtlDepthStencilStates.clear();
for (auto& pair : _transferImages) { delete pair.second; }
for (auto& pair : _transferImages) { pair.second->destroy(); }
_transferImages.clear();
[_cmdBlitImageLinearMTLSamplerState release];

View File

@ -58,8 +58,8 @@ VkResult MVKCommandPool::allocateCommandBuffers(const VkCommandBufferAllocateInf
void MVKCommandPool::freeCommandBuffers(uint32_t commandBufferCount,
const VkCommandBuffer* pCommandBuffers) {
for (uint32_t cbIdx = 0; cbIdx < commandBufferCount; cbIdx++) {
MVKCommandBuffer* mvkCmdBuff = MVKCommandBuffer::getMVKCommandBuffer(pCommandBuffers[cbIdx]);
delete mvkCmdBuff;
VkCommandBuffer cmdBuff = pCommandBuffers[cbIdx];
if (cmdBuff) { MVKCommandBuffer::getMVKCommandBuffer(cmdBuff)->destroy(); }
}
}

View File

@ -300,7 +300,7 @@ MVKImage* MVKCommandResourceFactory::newMVKImage(MVKImageDescriptorData& imgData
id<MTLFunction> MVKCommandResourceFactory::getFunctionNamed(const char* funcName) {
uint64_t startTime = _device->getPerformanceTimestamp();
id<MTLFunction> mtlFunc = [[_mtlLibrary newFunctionWithName: @(funcName)] autorelease];
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.functionRetrieval, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
return mtlFunc;
}
@ -311,7 +311,7 @@ id<MTLFunction> MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode,
id<MTLLibrary> mtlLib = [[getMTLDevice() newLibraryWithSource: mslSrcCode
options: shdrOpts
error: &err] autorelease];
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.mslCompile, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
if (err) {
mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Could not compile support shader from MSL source:\n%s\n %s (code %li) %s", mslSrcCode.UTF8String, err.localizedDescription.UTF8String, (long)err.code, err.localizedFailureReason.UTF8String);
return nil;
@ -319,7 +319,7 @@ id<MTLFunction> MVKCommandResourceFactory::newMTLFunction(NSString* mslSrcCode,
startTime = _device->getPerformanceTimestamp();
id<MTLFunction> mtlFunc = [mtlLib newFunctionWithName: funcName];
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.functionRetrieval, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
return mtlFunc;
}
@ -328,7 +328,7 @@ id<MTLRenderPipelineState> MVKCommandResourceFactory::newMTLRenderPipelineState(
NSError* err = nil;
id<MTLRenderPipelineState> rps = [getMTLDevice() newRenderPipelineStateWithDescriptor: plDesc error: &err]; // retained
MVKAssert( !err, "Could not create %s pipeline state: %s (code %li) %s", plDesc.label.UTF8String, err.localizedDescription.UTF8String, (long)err.code, err.localizedFailureReason.UTF8String);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.pipelineCompile, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.pipelineCompile, startTime);
return rps;
}
@ -360,7 +360,7 @@ void MVKCommandResourceFactory::initMTLLibrary() {
error: &err]; // retained
MVKAssert( !err, "Could not compile command shaders %s (code %li) %s", err.localizedDescription.UTF8String, (long)err.code, err.localizedFailureReason.UTF8String);
}
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.mslCompile, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
}
MVKCommandResourceFactory::~MVKCommandResourceFactory() {

View File

@ -95,9 +95,10 @@ VkResult MVKBuffer::pullFromDevice(VkDeviceSize offset, VkDeviceSize size) {
VkResult rslt = copyMTLBufferContent(offset, size, false);
// If we are pulling to populate a newly created device memory MTLBuffer,
// from a previously created local MTLBuffer, remove the local MTLBuffer now.
// from a previously created local MTLBuffer, remove the local MTLBuffer.
// Use autorelease in case the earlier MTLBuffer was encoded.
if (_mtlBuffer && _deviceMemory->getMTLBuffer()) {
[_mtlBuffer release];
[_mtlBuffer autorelease];
_mtlBuffer = nil;
}
@ -105,12 +106,7 @@ VkResult MVKBuffer::pullFromDevice(VkDeviceSize offset, VkDeviceSize size) {
}
void* MVKBuffer::map(VkDeviceSize offset, VkDeviceSize size) {
// MVKLogDebug("Comparing map to buffer %p with memory offset %d and size %d.", this, _deviceMemoryOffset, _byteCount);
// if (doesContain(offset, size)) { MVKLogDebug("Mapping %d bytes to single buffer %p.", size, this); }
return (doesContain(offset, size)
? (void*)((uintptr_t)getMTLBuffer().contents + mtlBufferRange(offset, size).location)
: VK_NULL_HANDLE);
return (void*)((uintptr_t)getMTLBuffer().contents + mtlBufferRange(offset, size).location);
}
// Copies host content into or out of the MTLBuffer.

View File

@ -634,9 +634,11 @@ VkResult MVKDescriptorPool::freeDescriptorSets(uint32_t count, const VkDescripto
for (uint32_t dsIdx = 0; dsIdx < count; dsIdx++) {
MVKDescriptorSet* mvkDS = (MVKDescriptorSet*)pDescriptorSets[dsIdx];
_allocatedSets.remove(mvkDS);
_allocatedSetCount--;
delete mvkDS;
if (mvkDS) {
_allocatedSets.remove(mvkDS);
_allocatedSetCount--;
mvkDS->destroy();
}
}
// MVKLogDebug("Pool %p freed %d descriptor sets for a new total of %d sets.", this, count, _allocatedSetCount);

View File

@ -60,13 +60,9 @@ class MVKCommandEncoder;
class MVKCommandResourceFactory;
#define kMVKVertexContentBufferIndex 0
/** The buffer index to use for vertex content. */
const static uint32_t kMVKVertexContentBufferIndex = 0;
#define MVK_MAX_QUEUE_FAMILIES 1
#define MVK_MIN_SWAPCHAIN_SURFACE_IMAGE_COUNT 2
#define MVK_MAX_SWAPCHAIN_SURFACE_IMAGE_COUNT 2 // Metal supports 3 concurrent drawables, but if the
// swapchain is destroyed and rebuilt as part of resizing,
// one will be held by the current display image.
#pragma mark -
#pragma mark MVKPhysicalDevice
@ -145,9 +141,6 @@ public:
#pragma mark Queues
/** Returns the number of queue families supported by this device. */
inline uint32_t getQueueFamilyCount() { return _queueFamilyCount; }
/**
* If properties is null, the value of pCount is updated with the number of
* queue families supported by this instance.
@ -240,11 +233,10 @@ protected:
MVKPhysicalDeviceMetalFeatures _metalFeatures;
VkPhysicalDeviceProperties _properties;
VkPhysicalDeviceMemoryProperties _memoryProperties;
VkQueueFamilyProperties _queueFamilyProperties[MVK_MAX_QUEUE_FAMILIES];
std::vector<MVKQueueFamily*> _queueFamilies;
uint32_t _allMemoryTypes;
uint32_t _hostVisibleMemoryTypes;
uint32_t _privateMemoryTypes;
uint32_t _queueFamilyCount;
};
@ -405,20 +397,20 @@ public:
}
/**
* If performance is being tracked, adds a shader compilation event with a duration
* If performance is being tracked, adds the performance for an activity with a duration
* interval between the start and end times, to the given performance statistics.
*
* If endTime is zero or not supplied, the current time is used.
*/
inline void addShaderCompilationEventPerformance(MVKShaderCompilationEventPerformance& shaderCompilationEvent,
uint64_t startTime, uint64_t endTime = 0) {
inline void addActivityPerformance(MVKPerformanceTracker& shaderCompilationEvent,
uint64_t startTime, uint64_t endTime = 0) {
if (_mvkConfig.performanceTracking) {
addShaderCompilationEventPerformanceImpl(shaderCompilationEvent, startTime, endTime);
addActivityPerformanceImpl(shaderCompilationEvent, startTime, endTime);
}
};
/** Populates the specified statistics structure from the current shader performance statistics. */
void getShaderCompilationPerformanceStatistics(MVKShaderCompilationPerformance* pShaderCompPerf);
/** Populates the specified statistics structure from the current activity performance statistics. */
void getPerformanceStatistics(MVKPerformanceStatistics* pPerf);
#pragma mark Metal
@ -482,8 +474,8 @@ public:
/** The MoltenVK configuration settings for this device. */
const MVKDeviceConfiguration _mvkConfig;
/** The shader compilation performance statistics. */
MVKShaderCompilationPerformance _shaderCompilationPerformance;
/** Performance statistics. */
MVKPerformanceStatistics _performanceStatistics;
#pragma mark Construction
@ -511,18 +503,17 @@ protected:
MVKResource* addResource(MVKResource* rez);
MVKResource* removeResource(MVKResource* rez);
void initPerformanceTracking();
const char* getShaderCompilationEventName(MVKShaderCompilationEventPerformance& shaderCompilationEvent);
const char* getActivityPerformanceDescription(MVKPerformanceTracker& shaderCompilationEvent);
uint64_t getPerformanceTimestampImpl();
void addShaderCompilationEventPerformanceImpl(MVKShaderCompilationEventPerformance& shaderCompilationEvent,
uint64_t startTime, uint64_t endTime);
void addActivityPerformanceImpl(MVKPerformanceTracker& shaderCompilationEvent,
uint64_t startTime, uint64_t endTime);
MVKPhysicalDevice* _physicalDevice;
MVKCommandResourceFactory* _commandResourceFactory;
std::vector<MVKQueueFamily*> _queueFamilies;
std::vector<MVKQueue*> _queues;
std::vector<std::vector<MVKQueue*>> _queuesByQueueFamilyIndex;
std::vector<MVKResource*> _resources;
std::mutex _rezLock;
std::mutex _shaderCompPerfLock;
std::mutex _perfLock;
id<MTLBuffer> _globalVisibilityResultMTLBuffer;
uint32_t _globalVisibilityQueryCount;
std::mutex _vizLock;

View File

@ -168,8 +168,11 @@ VkResult MVKPhysicalDevice::getSurfaceCapabilities(MVKSurface* surface,
VkExtent2D surfExtnt = mvkVkExtent2DFromCGSize(mtlLayer.updatedDrawableSizeMVK);
pSurfaceCapabilities->minImageCount = MVK_MIN_SWAPCHAIN_SURFACE_IMAGE_COUNT;
pSurfaceCapabilities->maxImageCount = MVK_MAX_SWAPCHAIN_SURFACE_IMAGE_COUNT;
// Metal supports 3 concurrent drawables, but if the swapchain is destroyed and
// rebuilt as part of resizing, one will be held by the current display image.
pSurfaceCapabilities->minImageCount = 2;
pSurfaceCapabilities->maxImageCount = 2;
pSurfaceCapabilities->currentExtent = surfExtnt;
pSurfaceCapabilities->minImageExtent = surfExtnt;
pSurfaceCapabilities->maxImageExtent = surfExtnt;
@ -263,23 +266,25 @@ VkResult MVKPhysicalDevice::getSurfacePresentModes(MVKSurface* surface,
VkResult MVKPhysicalDevice::getQueueFamilyProperties(uint32_t* pCount,
VkQueueFamilyProperties* queueProperties) {
uint32_t qfCnt = uint32_t(_queueFamilies.size());
// If properties aren't actually being requested yet, simply update the returned count
if ( !queueProperties ) {
*pCount = getQueueFamilyCount();
*pCount = qfCnt;
return VK_SUCCESS;
}
// Determine how many families we'll return, and return that number
uint32_t qCnt = getQueueFamilyCount();
VkResult result = (*pCount <= qCnt) ? VK_SUCCESS : VK_INCOMPLETE;
*pCount = min(*pCount, qCnt);
*pCount = min(*pCount, qfCnt);
// Now populate the queue families
for (uint32_t qIdx = 0; qIdx < *pCount; qIdx++) {
queueProperties[qIdx] = _queueFamilyProperties[qIdx];
if (queueProperties) {
for (uint32_t qfIdx = 0; qfIdx < *pCount; qfIdx++) {
_queueFamilies[qfIdx]->getProperties(&queueProperties[qfIdx]);
}
}
return result;
return (*pCount <= qfCnt) ? VK_SUCCESS : VK_INCOMPLETE;
}
@ -966,11 +971,16 @@ void MVKPhysicalDevice::logGPUInfo() {
void MVKPhysicalDevice::initQueueFamilies() {
// TODO: determine correct values
_queueFamilyCount = 1;
_queueFamilyProperties[0].queueFlags = (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT);
_queueFamilyProperties[0].queueCount = 16;
_queueFamilyProperties[0].timestampValidBits = 64;
_queueFamilyProperties[0].minImageTransferGranularity = { 1, 1, 1};
VkQueueFamilyProperties qfProps;
qfProps.queueFlags = (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT);
qfProps.queueCount = 8;
qfProps.timestampValidBits = 64;
qfProps.minImageTransferGranularity = { 1, 1, 1};
uint32_t qfCount = 1;
for (uint32_t qfIdx = 0; qfIdx < qfCount; qfIdx++) {
_queueFamilies.push_back(new MVKQueueFamily(this, qfIdx, &qfProps));
}
}
MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtlDevice) {
@ -986,6 +996,7 @@ MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtl
}
MVKPhysicalDevice::~MVKPhysicalDevice() {
mvkDestroyContainerContents(_queueFamilies);
[_mtlDevice release];
}
@ -998,12 +1009,16 @@ PFN_vkVoidFunction MVKDevice::getProcAddr(const char* pName) {
}
VkResult MVKDevice::getDeviceQueue(uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) {
*pQueue = _queueFamilies[queueFamilyIndex]->getQueue(queueIndex)->getVkQueue();
*pQueue = _queuesByQueueFamilyIndex[queueFamilyIndex][queueIndex]->getVkQueue();
return VK_SUCCESS;
}
VkResult MVKDevice::waitIdle() {
for (auto& q : _queues) { q->waitIdle(kMVKCommandUseDeviceWaitIdle); }
for (auto& queues : _queuesByQueueFamilyIndex) {
for (MVKQueue* q : queues) {
q->waitIdle(kMVKCommandUseDeviceWaitIdle);
}
}
return VK_SUCCESS;
}
@ -1327,9 +1342,9 @@ void MVKDevice::applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
uint64_t MVKDevice::getPerformanceTimestampImpl() { return mvkGetTimestamp(); }
void MVKDevice::addShaderCompilationEventPerformanceImpl(MVKShaderCompilationEventPerformance& shaderCompilationEvent,
uint64_t startTime, uint64_t endTime) {
lock_guard<mutex> lock(_shaderCompPerfLock);
void MVKDevice::addActivityPerformanceImpl(MVKPerformanceTracker& shaderCompilationEvent,
uint64_t startTime, uint64_t endTime) {
lock_guard<mutex> lock(_perfLock);
double currInterval = mvkGetElapsedMilliseconds(startTime, endTime);
shaderCompilationEvent.minimumDuration = min(currInterval, shaderCompilationEvent.minimumDuration);
@ -1337,8 +1352,8 @@ void MVKDevice::addShaderCompilationEventPerformanceImpl(MVKShaderCompilationEve
double totalInterval = (shaderCompilationEvent.averageDuration * shaderCompilationEvent.count++) + currInterval;
shaderCompilationEvent.averageDuration = totalInterval / shaderCompilationEvent.count;
MVKLogDebug("Shader building performance to %s curr: %.3f ms, avg: %.3f ms, min: %.3f ms, max: %.3f ms, count: %d",
getShaderCompilationEventName(shaderCompilationEvent),
MVKLogDebug("Performance to %s curr: %.3f ms, avg: %.3f ms, min: %.3f ms, max: %.3f ms, count: %d",
getActivityPerformanceDescription(shaderCompilationEvent),
currInterval,
shaderCompilationEvent.averageDuration,
shaderCompilationEvent.minimumDuration,
@ -1346,25 +1361,26 @@ void MVKDevice::addShaderCompilationEventPerformanceImpl(MVKShaderCompilationEve
shaderCompilationEvent.count);
}
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.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.shaderLibraryFromCache) { return "retrieve shader library from the cache."; }
if (&shaderCompilationEvent == &_shaderCompilationPerformance.functionRetrieval) { return "retrieve a MTLFunction from a MTLLibrary"; }
if (&shaderCompilationEvent == &_shaderCompilationPerformance.functionSpecialization) { return "specialize a retrieved MTLFunction"; }
if (&shaderCompilationEvent == &_shaderCompilationPerformance.pipelineCompile) { return "compile MTLFunctions into a pipeline"; }
if (&shaderCompilationEvent == &_shaderCompilationPerformance.sizePipelineCache) { return "calculate cache size required to write MSL to pipeline cache"; }
if (&shaderCompilationEvent == &_shaderCompilationPerformance.writePipelineCache) { return "write MSL to pipeline cache"; }
if (&shaderCompilationEvent == &_shaderCompilationPerformance.readPipelineCache) { return "read MSL from pipeline cache"; }
const char* MVKDevice::getActivityPerformanceDescription(MVKPerformanceTracker& shaderCompilationEvent) {
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.hashShaderCode) { return "hash shader SPIR-V code"; }
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.spirvToMSL) { return "convert SPIR-V to MSL source code"; }
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.mslCompile) { return "compile MSL source code into a MTLLibrary"; }
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.mslLoad) { return "load pre-compiled MSL code into a MTLLibrary"; }
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.shaderLibraryFromCache) { return "retrieve shader library from the cache"; }
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.functionRetrieval) { return "retrieve a MTLFunction from a MTLLibrary"; }
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.functionSpecialization) { return "specialize a retrieved MTLFunction"; }
if (&shaderCompilationEvent == &_performanceStatistics.shaderCompilation.pipelineCompile) { return "compile MTLFunctions into a pipeline"; }
if (&shaderCompilationEvent == &_performanceStatistics.pipelineCache.sizePipelineCache) { return "calculate cache size required to write MSL to pipeline cache"; }
if (&shaderCompilationEvent == &_performanceStatistics.pipelineCache.writePipelineCache) { return "write MSL to pipeline cache"; }
if (&shaderCompilationEvent == &_performanceStatistics.pipelineCache.readPipelineCache) { return "read MSL from pipeline cache"; }
if (&shaderCompilationEvent == &_performanceStatistics.queue.mtlQueueAccess) { return "access MTLCommandQueue"; }
return "Unknown shader compile event";
}
void MVKDevice::getShaderCompilationPerformanceStatistics(MVKShaderCompilationPerformance* pShaderCompPerf) {
lock_guard<mutex> lock(_shaderCompPerfLock);
void MVKDevice::getPerformanceStatistics(MVKPerformanceStatistics* pPerf) {
lock_guard<mutex> lock(_perfLock);
if (pShaderCompPerf) { *pShaderCompPerf = _shaderCompilationPerformance; }
if (pPerf) { *pPerf = _performanceStatistics; }
}
@ -1445,25 +1461,15 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
_commandResourceFactory = new MVKCommandResourceFactory(this);
// Create the queues
uint32_t qfCnt = _physicalDevice->getQueueFamilyCount();
VkQueueFamilyProperties qfProperties[qfCnt];
_physicalDevice->getQueueFamilyProperties(&qfCnt, qfProperties);
_queueFamilies.assign(qfCnt, VK_NULL_HANDLE);
// For each element in the queue record count, create a queue family with the requested number of queues.
uint32_t qrCnt = pCreateInfo->queueCreateInfoCount;
for (uint32_t qrIdx = 0; qrIdx < qrCnt; qrIdx++) {
const VkDeviceQueueCreateInfo* pQFInfo = &pCreateInfo->pQueueCreateInfos[qrIdx];
uint32_t qfIdx = pQFInfo->queueFamilyIndex;
if (_queueFamilies[qfIdx] == VK_NULL_HANDLE) {
MVKQueueFamily* qFam = new MVKQueueFamily(this, pQFInfo, &qfProperties[qfIdx]);
_queueFamilies[qfIdx] = qFam;
// Extract the queues from the queue family into a cache
uint32_t qCnt = qFam->getQueueCount();
for (uint32_t qIdx = 0; qIdx < qCnt; qIdx++) {
_queues.push_back(qFam->getQueue(qIdx));
}
MVKQueueFamily* qFam = _physicalDevice->_queueFamilies[qfIdx];
_queuesByQueueFamilyIndex.resize(qfIdx + 1); // Ensure an entry for this queue family exists
auto& queues = _queuesByQueueFamilyIndex[qfIdx];
for (uint32_t qIdx = 0; qIdx < pQFInfo->queueCount; qIdx++) {
queues.push_back(new MVKQueue(this, qFam, qIdx, pQFInfo->pQueuePriorities[qIdx]));
}
}
@ -1471,27 +1477,30 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
}
void MVKDevice::initPerformanceTracking() {
MVKShaderCompilationEventPerformance initPerf;
MVKPerformanceTracker initPerf;
initPerf.count = 0;
initPerf.averageDuration = 0.0;
initPerf.minimumDuration = numeric_limits<double>::max();
initPerf.maximumDuration = 0.0;
_shaderCompilationPerformance.hashShaderCode = initPerf;
_shaderCompilationPerformance.spirvToMSL = initPerf;
_shaderCompilationPerformance.mslCompile = initPerf;
_shaderCompilationPerformance.mslLoad = initPerf;
_shaderCompilationPerformance.shaderLibraryFromCache = initPerf;
_shaderCompilationPerformance.functionRetrieval = initPerf;
_shaderCompilationPerformance.functionSpecialization = initPerf;
_shaderCompilationPerformance.pipelineCompile = initPerf;
_shaderCompilationPerformance.sizePipelineCache = initPerf;
_shaderCompilationPerformance.writePipelineCache = initPerf;
_shaderCompilationPerformance.readPipelineCache = initPerf;
_performanceStatistics.shaderCompilation.hashShaderCode = initPerf;
_performanceStatistics.shaderCompilation.spirvToMSL = initPerf;
_performanceStatistics.shaderCompilation.mslCompile = initPerf;
_performanceStatistics.shaderCompilation.mslLoad = initPerf;
_performanceStatistics.shaderCompilation.shaderLibraryFromCache = initPerf;
_performanceStatistics.shaderCompilation.functionRetrieval = initPerf;
_performanceStatistics.shaderCompilation.functionSpecialization = initPerf;
_performanceStatistics.shaderCompilation.pipelineCompile = initPerf;
_performanceStatistics.pipelineCache.sizePipelineCache = initPerf;
_performanceStatistics.pipelineCache.writePipelineCache = initPerf;
_performanceStatistics.pipelineCache.readPipelineCache = initPerf;
_performanceStatistics.queue.mtlQueueAccess = initPerf;
}
MVKDevice::~MVKDevice() {
mvkDestroyContainerContents(_queueFamilies);
for (auto& queues : _queuesByQueueFamilyIndex) {
mvkDestroyContainerContents(queues);
}
[_globalVisibilityResultMTLBuffer release];
_commandResourceFactory->destroy();
}

View File

@ -110,7 +110,7 @@ protected:
friend MVKResource;
VkDeviceSize adjustMemorySize(VkDeviceSize size, VkDeviceSize offset);
bool mapToSingleResource(VkDeviceSize offset, VkDeviceSize size);
bool mapToUniqueResource(VkDeviceSize offset, VkDeviceSize size);
void addResource(MVKResource* rez);
void removeResource(MVKResource* rez);

View File

@ -59,7 +59,7 @@ VkResult MVKDeviceMemory::map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMa
VkDeviceSize mapSize = adjustMemorySize(size, offset);
// MVKLogDebug("Mapping device memory %p with offset %d and size %d.", this, offset, mapSize);
if ( !mapToSingleResource(offset, mapSize) ) {
if ( !mapToUniqueResource(offset, mapSize) ) {
if (isMemoryHostCoherent()) {
if ( !_mtlBuffer ) {
@ -109,15 +109,24 @@ void MVKDeviceMemory::unmap() {
_mapSize = 0;
}
// Attempts to map the memory defined by the offset and size to a single resource, and returns
// Attempts to map the memory defined by the offset and size to a unique resource, and returns
// whether such a mapping was possible. If it was, the mapped region is stored in _pMappedMemory.
bool MVKDeviceMemory::mapToSingleResource(VkDeviceSize offset, VkDeviceSize size) {
bool MVKDeviceMemory::mapToUniqueResource(VkDeviceSize offset, VkDeviceSize size) {
lock_guard<mutex> lock(_rezLock);
MVKResource* uniqueRez = nullptr;
for (auto& rez : _resources) {
_pMappedMemory = rez->map(offset, size);
if (_pMappedMemory) { return true; }
if (rez->doesContain(offset, size)) {
if (uniqueRez) { return false; } // More than one resource mapped to the region
uniqueRez = rez;
}
}
return false;
if (uniqueRez) {
_pMappedMemory = uniqueRez->map(offset, size);
return true;
}
return false;
}
void* MVKDeviceMemory::allocateMappedMemory(VkDeviceSize offset, VkDeviceSize size) {

View File

@ -204,9 +204,7 @@ VkResult MVKImage::pullFromDevice(VkDeviceSize offset, VkDeviceSize size) {
}
void* MVKImage::map(VkDeviceSize offset, VkDeviceSize size) {
return (doesContain(offset, size)
? _deviceMemory->allocateMappedMemory(offset, size)
: VK_NULL_HANDLE);
return _deviceMemory->allocateMappedMemory(offset, size);
}

View File

@ -81,7 +81,7 @@ MVKSurface* MVKInstance::createSurface(const Vk_PLATFORM_SurfaceCreateInfoMVK* p
void MVKInstance::destroySurface(MVKSurface* mvkSrfc,
const VkAllocationCallbacks* pAllocator) {
delete mvkSrfc;
mvkSrfc->destroy();
}
@ -245,7 +245,7 @@ void MVKInstance::initProcAddrs() {
ADD_PROC_ADDR(vkSetMoltenVKDeviceConfigurationMVK);
ADD_PROC_ADDR(vkGetPhysicalDeviceMetalFeaturesMVK);
ADD_PROC_ADDR(vkGetSwapchainPerformanceMVK);
ADD_PROC_ADDR(vkGetShaderCompilationPerformanceMVK);
ADD_PROC_ADDR(vkGetPerformanceStatisticsMVK);
ADD_PROC_ADDR(vkGetVersionStringsMVK);
ADD_PROC_ADDR(vkGetMTLDeviceMVK);
ADD_PROC_ADDR(vkSetMTLTextureMVK);

View File

@ -252,7 +252,7 @@ void MVKGraphicsPipeline::initMTLRenderPipelineState(const VkGraphicsPipelineCre
if (psError) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Could not create render pipeline:\n%s.", psError.description.UTF8String));
}
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.pipelineCompile, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.pipelineCompile, startTime);
}
}
}
@ -430,7 +430,7 @@ MVKComputePipeline::MVKComputePipeline(MVKDevice* device,
if (psError) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Could not create compute pipeline:\n%s.", psError.description.UTF8String));
}
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.pipelineCompile, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.pipelineCompile, startTime);
} else {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_INITIALIZATION_FAILED, "Compute shader function could not be compiled into pipeline. See previous error."));
}
@ -612,9 +612,9 @@ VkResult MVKPipelineCache::writeData(size_t* pDataSize, void* pData) {
// Serializes the data in this cache to a stream
void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) {
MVKShaderCompilationEventPerformance& shaderCompilationEvent = isCounting
? _device->_shaderCompilationPerformance.sizePipelineCache
: _device->_shaderCompilationPerformance.writePipelineCache;
MVKPerformanceTracker& shaderCompilationEvent = isCounting
? _device->_performanceStatistics.pipelineCache.sizePipelineCache
: _device->_performanceStatistics.pipelineCache.writePipelineCache;
uint32_t cacheEntryType;
cereal::BinaryOutputArchive writer(outstream);
@ -640,7 +640,7 @@ void MVKPipelineCache::writeData(ostream& outstream, bool isCounting) {
writer(cacheIter.getShaderContext());
writer(cacheIter.getEntryPoint());
writer(cacheIter.getMSL());
_device->addShaderCompilationEventPerformance(shaderCompilationEvent, startTime);
_device->addActivityPerformance(shaderCompilationEvent, startTime);
}
}
@ -705,7 +705,7 @@ void MVKPipelineCache::readData(const VkPipelineCacheCreateInfo* pCreateInfo) {
// Add the shader library to the staging cache.
MVKShaderLibraryCache* slCache = getShaderLibraryCache(smKey);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.readPipelineCache, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.pipelineCache.readPipelineCache, startTime);
slCache->addShaderLibrary(&shaderContext, msl, entryPoint);
break;
@ -748,7 +748,7 @@ MVKPipelineCache::MVKPipelineCache(MVKDevice* device, const VkPipelineCacheCreat
}
MVKPipelineCache::~MVKPipelineCache() {
for (auto& pair : _shaderCache) { delete pair.second; }
for (auto& pair : _shaderCache) { pair.second->destroy(); }
_shaderCache.clear();
}

View File

@ -30,37 +30,39 @@
class MVKQueue;
class MVKQueueSubmission;
class MVKPhysicalDevice;
#pragma mark -
#pragma mark MVKQueueFamily
/** Represents a Vulkan queue family. */
class MVKQueueFamily : public MVKBaseDeviceObject {
class MVKQueueFamily : public MVKConfigurableObject {
public:
/** Returns the index of this queue family. */
inline uint32_t getIndex() { return _queueFamilyIndex; }
/** Returns the number of queues allocated for this family. */
inline uint32_t getQueueCount() { return uint32_t(_queues.size()); }
/** Populates the specified properties structure. */
void getProperties(VkQueueFamilyProperties* queueProperties) {
if (queueProperties) { *queueProperties = _properties; }
}
/** Returns the queue at the specified index. */
inline MVKQueue* getQueue(uint32_t queueIndex) { return _queues[queueIndex]; }
/** Returns the MTLCommandQueue at the specified index. */
id<MTLCommandQueue> getMTLCommandQueue(uint32_t queueIndex);
/** Constructs an instance with the specified number of queues for the specified device. */
MVKQueueFamily(MVKDevice* device,
const VkDeviceQueueCreateInfo* pCreateInfo,
const VkQueueFamilyProperties* pProperties);
/** Constructs an instance with the specified index. */
MVKQueueFamily(MVKPhysicalDevice* physicalDevice, uint32_t queueFamilyIndex, const VkQueueFamilyProperties* pProperties);
~MVKQueueFamily() override;
protected:
MVKPhysicalDevice* _physicalDevice;
uint32_t _queueFamilyIndex;
VkQueueFamilyProperties _properties;
std::vector<MVKQueue*> _queues;
std::mutex _lock;
std::vector<id<MTLCommandQueue>> _mtlQueues;
std::mutex _qLock;
};

View File

@ -29,21 +29,28 @@ using namespace std;
#pragma mark -
#pragma mark MVKQueueFamily
MVKQueueFamily::MVKQueueFamily(MVKDevice* device,
const VkDeviceQueueCreateInfo* pCreateInfo,
const VkQueueFamilyProperties* pProperties) : MVKBaseDeviceObject(device) {
_properties = *pProperties;
// Create the queues
uint32_t qCnt = pCreateInfo->queueCount;
_queues.reserve(qCnt);
for (uint32_t qIdx = 0; qIdx < qCnt; qIdx++) {
_queues.push_back(new MVKQueue(_device, this, qIdx, pCreateInfo->pQueuePriorities[qIdx]));
// MTLCommandQueues are cached in MVKQueueFamily/MVKPhysicalDevice because they are very
// limited in number. An app that creates multiple VkDevices over time (such as a test suite)
// will soon find 15 second delays when creating subsequent MTLCommandQueues.
id<MTLCommandQueue> MVKQueueFamily::getMTLCommandQueue(uint32_t queueIndex) {
lock_guard<mutex> lock(_qLock);
id<MTLCommandQueue> mtlQ = _mtlQueues[queueIndex];
if ( !mtlQ ) {
mtlQ = [_physicalDevice->getMTLDevice() newCommandQueue]; // retained
_mtlQueues[queueIndex] = mtlQ;
}
return mtlQ;
}
MVKQueueFamily::MVKQueueFamily(MVKPhysicalDevice* physicalDevice, uint32_t queueFamilyIndex, const VkQueueFamilyProperties* pProperties) {
_physicalDevice = physicalDevice;
_queueFamilyIndex = queueFamilyIndex;
_properties = *pProperties;
_mtlQueues.assign(_properties.queueCount, nil);
}
MVKQueueFamily::~MVKQueueFamily() {
mvkDestroyContainerContents(_queues);
mvkReleaseContainerContents(_mtlQueues);
}
@ -123,7 +130,7 @@ VkResult MVKQueue::waitIdle(MVKCommandUse cmdBuffUse) {
// from a single thread.
id<MTLCommandBuffer> MVKQueue::makeMTLCommandBuffer(NSString* mtlCmdBuffLabel) {
// Retrieve a MTLCommandBuffer from the MTLQueue.
// Retrieve a MTLCommandBuffer from the MTLCommandQueue.
id<MTLCommandBuffer> mtlCmdBuffer = [_mtlQueue commandBufferWithUnretainedReferences];
mtlCmdBuffer.label = mtlCmdBuffLabel;
@ -208,7 +215,9 @@ void MVKQueue::initExecQueue() {
/** Creates and initializes the Metal queue. */
void MVKQueue::initMTLCommandQueue() {
_mtlQueue = [_device->getMTLDevice() newCommandQueue]; // retained
uint64_t startTime = _device->getPerformanceTimestamp();
_mtlQueue = _queueFamily->getMTLCommandQueue(_index); // not retained (cached in queue family)
_device->addActivityPerformance(_device->_performanceStatistics.queue.mtlQueueAccess, startTime);
[_mtlQueue insertDebugCaptureBoundary]; // Allow Xcode to capture the first frame if desired.
}
@ -223,7 +232,6 @@ MVKQueue::~MVKQueue() {
// in the destructor of the lock created in registerMTLCommandBufferCountdown().
lock_guard<mutex> lock(_completionLock);
destroyExecQueue();
[_mtlQueue release];
}
/** Destroys the execution dispatch queue. */
@ -337,7 +345,7 @@ void MVKQueueCommandBufferSubmission::finish() {
// If a fence exists, signal it.
if (_fence) { _fence->signal(); }
delete this;
this->destroy();
}
MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKDevice* device,
@ -403,7 +411,7 @@ void MVKQueuePresentSurfaceSubmission::execute() {
// Let Xcode know the frame is done, in case command buffer is not used
if (_device->_mvkConfig.debugMode) { [mtlQ insertDebugCaptureBoundary]; }
delete this;
this->destroy();
}
MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKDevice* device,

View File

@ -46,7 +46,7 @@ bool MVKResource::needsHostReadSync(VkPipelineStageFlags srcStageMask,
#if MVK_MACOS
return (mvkIsAnyFlagEnabled(dstStageMask, (VK_PIPELINE_STAGE_HOST_BIT)) &&
mvkIsAnyFlagEnabled(pMemoryBarrier->dstAccessMask, (VK_ACCESS_HOST_READ_BIT)) &&
_deviceMemory->isMemoryHostAccessible() && !_deviceMemory->isMemoryHostCoherent());
_deviceMemory && _deviceMemory->isMemoryHostAccessible() && !_deviceMemory->isMemoryHostCoherent());
#endif
}

View File

@ -58,6 +58,9 @@ public:
const void* mslCompiledCodeData,
size_t mslCompiledCodeLength);
/** Copy constructor. */
MVKShaderLibrary(MVKShaderLibrary& other);
~MVKShaderLibrary() override;
protected:

View File

@ -50,7 +50,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
uint64_t startTime = _device->getPerformanceTimestamp();
id<MTLFunction> mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName] autorelease];
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.functionRetrieval, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionRetrieval, startTime);
if (mtlFunc) {
// If the Metal device supports shader specialization, and the Metal function expects to be
@ -83,7 +83,7 @@ MVKMTLFunction MVKShaderLibrary::getMTLFunction(const VkSpecializationInfo* pSpe
NSError* err = nil;
mtlFunc = [[_mtlLibrary newFunctionWithName: mtlFuncName constantValues: mtlFCVals error: &err] autorelease];
handleCompilationError(err, "Shader function specialization");
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.functionSpecialization, startTimeSpec);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.functionSpecialization, startTimeSpec);
}
}
} else {
@ -130,7 +130,7 @@ MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device, const string& mslSourceCod
error: &err]; // retained
handleCompilationError(err, "Shader module compilation");
}
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.mslCompile, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslCompile, startTime);
_entryPoint = entryPoint;
_msl = mslSourceCode;
@ -150,7 +150,13 @@ MVKShaderLibrary::MVKShaderLibrary(MVKDevice* device,
handleCompilationError(err, "Compiled shader module creation");
[shdrData release];
}
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.mslLoad, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.mslLoad, startTime);
}
MVKShaderLibrary::MVKShaderLibrary(MVKShaderLibrary& other) : MVKBaseDeviceObject(other._device) {
_mtlLibrary = [other._mtlLibrary retain];
_entryPoint = other._entryPoint;
_msl = other._msl;
}
// If err object is nil, the compilation succeeded without any warnings.
@ -204,7 +210,7 @@ MVKShaderLibrary* MVKShaderLibraryCache::findShaderLibrary(SPIRVToMSLConverterCo
return slPair.second;
}
}
return NULL;
return nullptr;
}
// Adds and returns a new shader library configured from the specified context.
@ -212,7 +218,7 @@ MVKShaderLibrary* MVKShaderLibraryCache::addShaderLibrary(SPIRVToMSLConverterCon
const string& mslSourceCode,
const SPIRVEntryPoint& entryPoint) {
MVKShaderLibrary* shLib = new MVKShaderLibrary(_device, mslSourceCode, entryPoint);
_shaderLibraries.push_back(pair<SPIRVToMSLConverterContext, MVKShaderLibrary*>(*pContext, shLib));
_shaderLibraries.emplace_back(*pContext, shLib);
return shLib;
}
@ -221,13 +227,13 @@ void MVKShaderLibraryCache::merge(MVKShaderLibraryCache* other) {
if ( !other ) { return; }
for (auto& otherPair : other->_shaderLibraries) {
if ( !findShaderLibrary(&otherPair.first) ) {
_shaderLibraries.push_back(otherPair);
_shaderLibraries.emplace_back(otherPair.first, new MVKShaderLibrary(*otherPair.second));
}
}
}
MVKShaderLibraryCache::~MVKShaderLibraryCache() {
for (auto& slPair : _shaderLibraries) { delete slPair.second; }
for (auto& slPair : _shaderLibraries) { slPair.second->destroy(); }
}
@ -246,7 +252,7 @@ MVKMTLFunction MVKShaderModule::getMTLFunction(SPIRVToMSLConverterContext* pCont
} else {
mvkLib = _shaderLibraryCache.getShaderLibrary(pContext, this);
}
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.shaderLibraryFromCache, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.shaderLibraryFromCache, startTime);
}
return mvkLib ? mvkLib->getMTLFunction(pSpecializationInfo) : MVKMTLFunctionNull;
}
@ -256,7 +262,7 @@ bool MVKShaderModule::convert(SPIRVToMSLConverterContext* pContext) {
uint64_t startTime = _device->getPerformanceTimestamp();
bool wasConverted = _converter.convert(*pContext, shouldLogCode, shouldLogCode, shouldLogCode);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.spirvToMSL, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.spirvToMSL, startTime);
if (wasConverted) {
if (shouldLogCode) { MVKLogInfo("%s", _converter.getResultLog().data()); }
@ -293,7 +299,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(pCreateInfo->pCode, spvCount);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
_converter.setSPIRV(pCreateInfo->pCode, spvCount);
@ -307,7 +313,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(&magicNum);
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
_converter.setMSL(pMSLCode, nullptr);
_defaultLibrary = new MVKShaderLibrary(_device, _converter.getMSL().c_str(), _converter.getEntryPoint());
@ -322,7 +328,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(&magicNum);
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);
_device->addActivityPerformance(_device->_performanceStatistics.shaderCompilation.hashShaderCode, startTime);
_defaultLibrary = new MVKShaderLibrary(_device, (void*)(pMSLCode), mslCodeLen);
@ -337,6 +343,6 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
}
MVKShaderModule::~MVKShaderModule() {
if (_defaultLibrary) { delete _defaultLibrary; }
if (_defaultLibrary) { _defaultLibrary->destroy(); }
}

View File

@ -119,8 +119,8 @@ void MVKSwapchain::renderWatermark(id<MTLTexture> mtlTexture, id<MTLCommandBuffe
_licenseWatermark->render(mtlTexture, mtlCmdBuff, _performanceStatistics.lastFrameInterval);
} else {
if (_licenseWatermark) {
delete _licenseWatermark;
_licenseWatermark = NULL;
_licenseWatermark->destroy();
_licenseWatermark = nullptr;
}
}
}
@ -230,8 +230,12 @@ void MVKSwapchain::initSurfaceImages(const VkSwapchainCreateInfoKHR* pCreateInfo
.flags = 0,
};
uint32_t imgCnt = MVK_MAX_SWAPCHAIN_SURFACE_IMAGE_COUNT;
_surfaceImages.reserve(imgCnt);
VkSurfaceCapabilitiesKHR srfcProps;
MVKSurface* mvkSrfc = (MVKSurface*)pCreateInfo->surface;
_device->getPhysicalDevice()->getSurfaceCapabilities(mvkSrfc, &srfcProps);
uint32_t imgCnt = srfcProps.maxImageCount;
_surfaceImages.reserve(imgCnt);
for (uint32_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) {
_surfaceImages.push_back(_device->createSwapchainImage(&imgInfo, this, NULL));
}
@ -256,6 +260,6 @@ void MVKSwapchain::initFrameIntervalTracking() {
MVKSwapchain::~MVKSwapchain() {
for (auto& img : _surfaceImages) { _device->destroySwapchainImage(img, NULL); }
if (_licenseWatermark) { delete _licenseWatermark; }
if (_licenseWatermark) { _licenseWatermark->destroy(); }
}

View File

@ -282,7 +282,7 @@ void mvkEnsureSize(C& container, S size) {
*/
template<typename C>
void mvkDestroyContainerContents(C& container) {
for (auto elem : container) { delete elem; }
for (auto elem : container) { elem->destroy(); }
container.clear();
}

View File

@ -38,7 +38,7 @@
* or somewhat faster, but not-thread-safe manner.
*
* An instance of this pool can be configured to either manage a pool of objects,
* or simply allocate a new object instance on each request and delete the object
* or simply allocate a new object instance on each request and destroy the object
* when it is released back to the pool.
*/
template <class T>
@ -82,7 +82,7 @@ public:
_tail = obj;
if ( !_head ) { _head = obj; }
} else {
delete obj;
obj->destroy();
}
}
@ -101,7 +101,7 @@ public:
/** Clears all the objects from this pool, deleting each one. This method is thread-safe. */
void clear() {
std::lock_guard<std::mutex> lock(_lock);
while ( T* obj = nextObject() ) { delete obj; }
while ( T* obj = nextObject() ) { obj->destroy(); }
}
/**

View File

@ -19,6 +19,7 @@
#pragma once
#include "MVKBaseObject.h"
#include <string>
#import <Metal/Metal.h>
@ -53,7 +54,7 @@ typedef struct MVKWatermarkColor {
*
* This class uses Metal directly.
*/
class MVKWatermark {
class MVKWatermark : public MVKBaseObject {
public:

View File

@ -60,12 +60,11 @@ MVK_PUBLIC_SYMBOL void vkGetSwapchainPerformanceMVK(
mvkSwapchain->getPerformanceStatistics(pSwapchainPerf);
}
MVK_PUBLIC_SYMBOL void vkGetShaderCompilationPerformanceMVK(
MVK_PUBLIC_SYMBOL void vkGetPerformanceStatisticsMVK(
VkDevice device,
MVKShaderCompilationPerformance* pShaderCompPerf) {
MVKPerformanceStatistics* pPerf) {
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->getShaderCompilationPerformanceStatistics(pShaderCompPerf);
MVKDevice::getMVKDevice(device)->getPerformanceStatistics(pPerf);
}
MVK_PUBLIC_SYMBOL void vkGetVersionStringsMVK(

View File

@ -60,6 +60,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyInstance(
VkInstance instance,
const VkAllocationCallbacks* pAllocator) {
if ( !instance ) { return; }
MVKInstance::getMVKInstance(instance)->destroy();
}
@ -112,11 +113,11 @@ MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceProperties(
MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceQueueFamilyProperties(
VkPhysicalDevice physicalDevice,
uint32_t* pCount,
uint32_t* pQueueFamilyPropertyCount,
VkQueueFamilyProperties* pQueueFamilyProperties) {
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
mvkPD->getQueueFamilyProperties(pCount, pQueueFamilyProperties);
mvkPD->getQueueFamilyProperties(pQueueFamilyPropertyCount, pQueueFamilyProperties);
}
MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceMemoryProperties(
@ -167,6 +168,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyDevice(
VkDevice device,
const VkAllocationCallbacks* pAllocator) {
if ( !device ) { return; }
MVKDevice::getMVKDevice(device)->destroy();
}
@ -256,6 +258,7 @@ MVK_PUBLIC_SYMBOL void vkFreeMemory(
VkDeviceMemory mem,
const VkAllocationCallbacks* pAllocator) {
if ( !mem ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->freeMemory((MVKDeviceMemory*)mem, pAllocator);
}
@ -405,6 +408,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyFence(
VkFence fence,
const VkAllocationCallbacks* pAllocator) {
if ( !fence ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyFence((MVKFence*)fence, pAllocator);
}
@ -452,6 +456,7 @@ MVK_PUBLIC_SYMBOL void vkDestroySemaphore(
VkSemaphore semaphore,
const VkAllocationCallbacks* pAllocator) {
if ( !semaphore ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroySemaphore((MVKSemaphore*)semaphore, pAllocator);
}
@ -470,6 +475,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyEvent(
VkEvent event,
const VkAllocationCallbacks* pAllocator) {
if ( !event ) { return; }
MVKLogUnimplemented("vkDestroyEvent");
}
@ -511,6 +517,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyQueryPool(
VkQueryPool queryPool,
const VkAllocationCallbacks* pAllocator) {
if ( !queryPool ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyQueryPool((MVKQueryPool*)queryPool, pAllocator);
}
@ -546,6 +553,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyBuffer(
VkBuffer buffer,
const VkAllocationCallbacks* pAllocator) {
if ( !buffer ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyBuffer((MVKBuffer*)buffer, pAllocator);
}
@ -567,6 +575,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyBufferView(
VkBufferView bufferView,
const VkAllocationCallbacks* pAllocator) {
if ( !bufferView ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyBufferView((MVKBufferView*)bufferView, pAllocator);
}
@ -588,6 +597,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyImage(
VkImage image,
const VkAllocationCallbacks* pAllocator) {
if ( !image ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyImage((MVKImage*)image, pAllocator);
}
@ -619,6 +629,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyImageView(
VkImageView imageView,
const VkAllocationCallbacks* pAllocator) {
if ( !imageView ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyImageView((MVKImageView*)imageView, pAllocator);
}
@ -640,6 +651,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyShaderModule(
VkShaderModule shaderModule,
const VkAllocationCallbacks* pAllocator) {
if ( !shaderModule ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyShaderModule((MVKShaderModule*)shaderModule, pAllocator);
}
@ -661,6 +673,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyPipelineCache(
VkPipelineCache pipelineCache,
const VkAllocationCallbacks* pAllocator) {
if ( !pipelineCache ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyPipelineCache((MVKPipelineCache*)pipelineCache, pAllocator);
}
@ -714,6 +727,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyPipeline(
VkPipeline pipeline,
const VkAllocationCallbacks* pAllocator) {
if ( !pipeline ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyPipeline((MVKPipeline*)pipeline, pAllocator);
}
@ -735,6 +749,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyPipelineLayout(
VkPipelineLayout pipelineLayout,
const VkAllocationCallbacks* pAllocator) {
if ( !pipelineLayout ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyPipelineLayout((MVKPipelineLayout*)pipelineLayout, pAllocator);
}
@ -756,6 +771,7 @@ MVK_PUBLIC_SYMBOL void vkDestroySampler(
VkSampler sampler,
const VkAllocationCallbacks* pAllocator) {
if ( !sampler ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroySampler((MVKSampler*)sampler, pAllocator);
}
@ -777,6 +793,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyDescriptorSetLayout(
VkDescriptorSetLayout descriptorSetLayout,
const VkAllocationCallbacks* pAllocator) {
if ( !descriptorSetLayout ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyDescriptorSetLayout((MVKDescriptorSetLayout*)descriptorSetLayout, pAllocator);
}
@ -798,6 +815,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyDescriptorPool(
VkDescriptorPool descriptorPool,
const VkAllocationCallbacks* pAllocator) {
if ( !descriptorPool ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyDescriptorPool((MVKDescriptorPool*)descriptorPool, pAllocator);
}
@ -859,6 +877,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyFramebuffer(
VkFramebuffer framebuffer,
const VkAllocationCallbacks* pAllocator) {
if ( !framebuffer ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyFramebuffer((MVKFramebuffer*)framebuffer, pAllocator);
}
@ -880,6 +899,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyRenderPass(
VkRenderPass renderPass,
const VkAllocationCallbacks* pAllocator) {
if ( !renderPass ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyRenderPass((MVKRenderPass*)renderPass, pAllocator);
}
@ -912,6 +932,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyCommandPool(
VkCommandPool commandPool,
const VkAllocationCallbacks* pAllocator) {
if ( !commandPool ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroyCommandPool((MVKCommandPool*)commandPool, pAllocator);
}
@ -1471,6 +1492,7 @@ MVK_PUBLIC_SYMBOL void vkDestroySwapchainKHR(
VkSwapchainKHR swapchain,
const VkAllocationCallbacks* pAllocator) {
if ( !swapchain ) { return; }
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
mvkDev->destroySwapchain((MVKSwapchain*)swapchain, pAllocator);
}
@ -1514,6 +1536,7 @@ MVK_PUBLIC_SYMBOL void vkDestroySurfaceKHR(
VkSurfaceKHR surface,
const VkAllocationCallbacks* pAllocator) {
if ( !surface ) { return; }
MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
mvkInst->destroySurface((MVKSurface*)surface, pAllocator);
}