Merge pull request #538 from billhollings/master

Track enabled device features and clean up sparse binding errors.
This commit is contained in:
Bill Hollings 2019-03-25 22:48:57 -04:00 committed by GitHub
commit 89a3a511c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 198 additions and 30 deletions

View File

@ -22,6 +22,7 @@ Released TBD
- Add correct function entry point handling. - Add correct function entry point handling.
- Add support for `VK_KHR_get_surface_capabilities2` extension. - Add support for `VK_KHR_get_surface_capabilities2` extension.
- Implement newer `VK_KHR_swapchain` extension functions. - Implement newer `VK_KHR_swapchain` extension functions.
- Add support for tracking device features enabled during `vkCreateDevice()`.
- Allow zero offset and stride combo in `VkVertexInputBindingDescription`. - Allow zero offset and stride combo in `VkVertexInputBindingDescription`.
- Fix conditions when multiple functions return VK_INCOMPLETE. - Fix conditions when multiple functions return VK_INCOMPLETE.
- Fix potential memory leak on synchronous command buffer submission. - Fix potential memory leak on synchronous command buffer submission.

View File

@ -148,7 +148,7 @@ void MVKCmdSetLineWidth::setContent(float lineWidth) {
// Validate // Validate
clearConfigurationResult(); clearConfigurationResult();
if (_lineWidth != 1.0 || getDevice()->_pFeatures->wideLines) { if (_lineWidth != 1.0 || getDevice()->_enabledFeatures.wideLines) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetLineWidth(): The current device does not support wide lines.")); setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetLineWidth(): The current device does not support wide lines."));
} }
} }
@ -207,7 +207,7 @@ void MVKCmdSetDepthBounds::setContent(float minDepthBounds, float maxDepthBounds
// Validate // Validate
clearConfigurationResult(); clearConfigurationResult();
if (getDevice()->_pFeatures->depthBounds) { if (getDevice()->_enabledFeatures.depthBounds) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetDepthBounds(): The current device does not support setting depth bounds.")); setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetDepthBounds(): The current device does not support setting depth bounds."));
} }
} }

View File

@ -532,7 +532,7 @@ MVKCommandEncoder::MVKCommandEncoder(MVKCommandBuffer* cmdBuffer) : MVKBaseDevic
_computeResourcesState(this), _computeResourcesState(this),
_occlusionQueryState(this) { _occlusionQueryState(this) {
_pDeviceFeatures = _device->_pFeatures; _pDeviceFeatures = &_device->_enabledFeatures;
_pDeviceMetalFeatures = _device->_pMetalFeatures; _pDeviceMetalFeatures = _device->_pMetalFeatures;
_pDeviceProperties = _device->_pProperties; _pDeviceProperties = _device->_pProperties;
_pDeviceMemoryProperties = _device->_pMemoryProperties; _pDeviceMemoryProperties = _device->_pMemoryProperties;

View File

@ -73,7 +73,7 @@ void MVKViewportCommandEncoderState::setViewports(const MVKVector<MTLViewport> &
void MVKViewportCommandEncoderState::encodeImpl(uint32_t stage) { void MVKViewportCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; } if (stage != kMVKGraphicsStageRasterization) { return; }
MVKAssert(!_mtlViewports.empty(), "Must specify at least one viewport"); MVKAssert(!_mtlViewports.empty(), "Must specify at least one viewport");
if (_cmdEncoder->getDevice()->_pFeatures->multiViewport) { if (_cmdEncoder->_pDeviceFeatures->multiViewport) {
[_cmdEncoder->_mtlRenderEncoder setViewports: &_mtlViewports[0] count: _mtlViewports.size()]; [_cmdEncoder->_mtlRenderEncoder setViewports: &_mtlViewports[0] count: _mtlViewports.size()];
} else { } else {
[_cmdEncoder->_mtlRenderEncoder setViewport: _mtlViewports[0]]; [_cmdEncoder->_mtlRenderEncoder setViewport: _mtlViewports[0]];
@ -115,7 +115,7 @@ void MVKScissorCommandEncoderState::encodeImpl(uint32_t stage) {
std::for_each(clippedScissors.begin(), clippedScissors.end(), [this](MTLScissorRect& scissor) { std::for_each(clippedScissors.begin(), clippedScissors.end(), [this](MTLScissorRect& scissor) {
scissor = _cmdEncoder->clipToRenderArea(scissor); scissor = _cmdEncoder->clipToRenderArea(scissor);
}); });
if (_cmdEncoder->getDevice()->_pFeatures->multiViewport) { if (_cmdEncoder->_pDeviceFeatures->multiViewport) {
[_cmdEncoder->_mtlRenderEncoder setScissorRects: &clippedScissors[0] count: clippedScissors.size()]; [_cmdEncoder->_mtlRenderEncoder setScissorRects: &clippedScissors[0] count: clippedScissors.size()];
} else { } else {
[_cmdEncoder->_mtlRenderEncoder setScissorRect: clippedScissors[0]]; [_cmdEncoder->_mtlRenderEncoder setScissorRect: clippedScissors[0]];

View File

@ -583,8 +583,18 @@ public:
/** Pointer to the MoltenVK configuration settings. */ /** Pointer to the MoltenVK configuration settings. */
const MVKConfiguration* _pMVKConfig; const MVKConfiguration* _pMVKConfig;
/** Pointer to the feature set of the underlying physical device. */ /** Device features available and enabled. */
const VkPhysicalDeviceFeatures* _pFeatures; const VkPhysicalDeviceFeatures _enabledFeatures;
const VkPhysicalDevice16BitStorageFeatures _enabledStorage16Features;
const VkPhysicalDevice8BitStorageFeaturesKHR _enabledStorage8Features;
const VkPhysicalDeviceFloat16Int8FeaturesKHR _enabledF16I8Features;
const VkPhysicalDeviceVariablePointerFeatures _enabledVarPtrFeatures;
const VkPhysicalDeviceHostQueryResetFeaturesEXT _enabledHostQryResetFeatures;
const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT _enabledVtxAttrDivFeatures;
const VkPhysicalDevicePortabilitySubsetFeaturesEXTX _enabledPortabilityFeatures;
/** The list of Vulkan extensions, indicating whether each has been enabled by the app for this device. */
const MVKExtensionList _enabledExtensions;
/** Pointer to the Metal-specific features of the underlying physical device. */ /** Pointer to the Metal-specific features of the underlying physical device. */
const MVKPhysicalDeviceMetalFeatures* _pMetalFeatures; const MVKPhysicalDeviceMetalFeatures* _pMetalFeatures;
@ -595,9 +605,6 @@ public:
/** Pointer to the memory properties of the underlying physical device. */ /** Pointer to the memory properties of the underlying physical device. */
const VkPhysicalDeviceMemoryProperties* _pMemoryProperties; const VkPhysicalDeviceMemoryProperties* _pMemoryProperties;
/** The list of Vulkan extensions, indicating whether each has been enabled by the app for this device. */
const MVKExtensionList _enabledExtensions;
/** Performance statistics. */ /** Performance statistics. */
MVKPerformanceStatistics _performanceStatistics; MVKPerformanceStatistics _performanceStatistics;
@ -629,6 +636,9 @@ protected:
void initPerformanceTracking(); void initPerformanceTracking();
void initPhysicalDevice(MVKPhysicalDevice* physicalDevice); void initPhysicalDevice(MVKPhysicalDevice* physicalDevice);
void initQueues(const VkDeviceCreateInfo* pCreateInfo); void initQueues(const VkDeviceCreateInfo* pCreateInfo);
void enableFeatures(const VkDeviceCreateInfo* pCreateInfo);
void enableFeatures(const VkBool32* pEnable, const VkBool32* pRequested, const VkBool32* pAvailable, uint32_t count);
void enableExtensions(const VkDeviceCreateInfo* pCreateInfo);
const char* getActivityPerformanceDescription(MVKPerformanceTracker& shaderCompilationEvent); const char* getActivityPerformanceDescription(MVKPerformanceTracker& shaderCompilationEvent);
uint64_t getPerformanceTimestampImpl(); uint64_t getPerformanceTimestampImpl();
void addActivityPerformanceImpl(MVKPerformanceTracker& shaderCompilationEvent, void addActivityPerformanceImpl(MVKPerformanceTracker& shaderCompilationEvent,

View File

@ -2036,21 +2036,27 @@ uint32_t MVKDevice::expandVisibilityResultMTLBuffer(uint32_t queryCount) {
#pragma mark Construction #pragma mark Construction
MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo) { MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo) :
_enabledFeatures(),
_enabledStorage16Features(),
_enabledStorage8Features(),
_enabledF16I8Features(),
_enabledVarPtrFeatures(),
_enabledHostQryResetFeatures(),
_enabledVtxAttrDivFeatures(),
_enabledPortabilityFeatures()
{
initPerformanceTracking(); initPerformanceTracking();
initPhysicalDevice(physicalDevice); initPhysicalDevice(physicalDevice);
enableFeatures(pCreateInfo);
enableExtensions(pCreateInfo);
_globalVisibilityResultMTLBuffer = nil; _globalVisibilityResultMTLBuffer = nil;
_globalVisibilityQueryCount = 0; _globalVisibilityQueryCount = 0;
_commandResourceFactory = new MVKCommandResourceFactory(this); _commandResourceFactory = new MVKCommandResourceFactory(this);
MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_enabledExtensions;
setConfigurationResult(pWritableExtns->enable(pCreateInfo->enabledExtensionCount,
pCreateInfo->ppEnabledExtensionNames,
getInstance()->getDriverLayer()->getSupportedExtensions()));
initQueues(pCreateInfo); initQueues(pCreateInfo);
string logMsg = "Created VkDevice to run on GPU %s with the following Vulkan extensions enabled:"; string logMsg = "Created VkDevice to run on GPU %s with the following Vulkan extensions enabled:";
@ -2083,7 +2089,6 @@ void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice) {
_physicalDevice = physicalDevice; _physicalDevice = physicalDevice;
_pMVKConfig = _physicalDevice->_mvkInstance->getMoltenVKConfiguration(); _pMVKConfig = _physicalDevice->_mvkInstance->getMoltenVKConfiguration();
_pFeatures = &_physicalDevice->_features;
_pMetalFeatures = _physicalDevice->getMetalFeatures(); _pMetalFeatures = _physicalDevice->getMetalFeatures();
_pProperties = &_physicalDevice->_properties; _pProperties = &_physicalDevice->_properties;
_pMemoryProperties = &_physicalDevice->_memoryProperties; _pMemoryProperties = &_physicalDevice->_memoryProperties;
@ -2103,6 +2108,142 @@ void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice) {
#endif #endif
} }
void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
// Start with all features disabled
memset((void*)&_enabledFeatures, 0, sizeof(_enabledFeatures));
memset((void*)&_enabledStorage16Features, 0, sizeof(_enabledStorage16Features));
memset((void*)&_enabledStorage8Features, 0, sizeof(_enabledStorage8Features));
memset((void*)&_enabledF16I8Features, 0, sizeof(_enabledF16I8Features));
memset((void*)&_enabledVarPtrFeatures, 0, sizeof(_enabledVarPtrFeatures));
memset((void*)&_enabledHostQryResetFeatures, 0, sizeof(_enabledHostQryResetFeatures));
memset((void*)&_enabledVtxAttrDivFeatures, 0, sizeof(_enabledVtxAttrDivFeatures));
memset((void*)&_enabledPortabilityFeatures, 0, sizeof(_enabledPortabilityFeatures));
// Fetch the available physical device features.
VkPhysicalDevicePortabilitySubsetFeaturesEXTX pdPortabilityFeatures;
pdPortabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_EXTX;
pdPortabilityFeatures.pNext = NULL;
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT pdVtxAttrDivFeatures;
pdVtxAttrDivFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
pdVtxAttrDivFeatures.pNext = &pdPortabilityFeatures;
VkPhysicalDeviceHostQueryResetFeaturesEXT pdHostQryResetFeatures;
pdHostQryResetFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT;
pdHostQryResetFeatures.pNext = &pdVtxAttrDivFeatures;
VkPhysicalDeviceVariablePointerFeatures pdVarPtrFeatures;
pdVarPtrFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES;
pdVarPtrFeatures.pNext = &pdHostQryResetFeatures;
VkPhysicalDeviceFloat16Int8FeaturesKHR pdF16I8Features;
pdF16I8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
pdF16I8Features.pNext = &pdVarPtrFeatures;
VkPhysicalDevice8BitStorageFeaturesKHR pdStorage8Features;
pdStorage8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR;
pdStorage8Features.pNext = &pdF16I8Features;
VkPhysicalDevice16BitStorageFeatures pdStorage16Features;
pdStorage16Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES;
pdStorage16Features.pNext = &pdStorage8Features;
VkPhysicalDeviceFeatures2 pdFeats2;
pdFeats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
pdFeats2.pNext = &pdStorage16Features;
_physicalDevice->getFeatures(&pdFeats2);
//Enable device features based on requested and available features
if (pCreateInfo->pEnabledFeatures) {
enableFeatures(&_enabledFeatures.robustBufferAccess,
&pCreateInfo->pEnabledFeatures->robustBufferAccess,
&pdFeats2.features.robustBufferAccess, 55);
}
auto* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext;
while (next) {
switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: {
auto* requestedFeatures = (VkPhysicalDeviceFeatures2*)next;
enableFeatures(&_enabledFeatures.robustBufferAccess,
&requestedFeatures->features.robustBufferAccess,
&pdFeats2.features.robustBufferAccess, 55);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
auto* requestedFeatures = (VkPhysicalDevice16BitStorageFeatures*)next;
enableFeatures(&_enabledStorage16Features.storageBuffer16BitAccess,
&requestedFeatures->storageBuffer16BitAccess,
&pdStorage16Features.storageBuffer16BitAccess, 4);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
auto* requestedFeatures = (VkPhysicalDevice8BitStorageFeaturesKHR*)next;
enableFeatures(&_enabledStorage8Features.storageBuffer8BitAccess,
&requestedFeatures->storageBuffer8BitAccess,
&pdStorage8Features.storageBuffer8BitAccess, 3);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR: {
auto* requestedFeatures = (VkPhysicalDeviceFloat16Int8FeaturesKHR*)next;
enableFeatures(&_enabledF16I8Features.shaderFloat16,
&requestedFeatures->shaderFloat16,
&pdF16I8Features.shaderFloat16, 2);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
auto* requestedFeatures = (VkPhysicalDeviceVariablePointerFeatures*)next;
enableFeatures(&_enabledVarPtrFeatures.variablePointersStorageBuffer,
&requestedFeatures->variablePointersStorageBuffer,
&pdVarPtrFeatures.variablePointersStorageBuffer, 2);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: {
auto* requestedFeatures = (VkPhysicalDeviceHostQueryResetFeaturesEXT*)next;
enableFeatures(&_enabledHostQryResetFeatures.hostQueryReset,
&requestedFeatures->hostQueryReset,
&pdHostQryResetFeatures.hostQueryReset, 1);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
auto* requestedFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next;
enableFeatures(&_enabledVtxAttrDivFeatures.vertexAttributeInstanceRateDivisor,
&requestedFeatures->vertexAttributeInstanceRateDivisor,
&pdVtxAttrDivFeatures.vertexAttributeInstanceRateDivisor, 2);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_EXTX: {
auto* requestedFeatures = (VkPhysicalDevicePortabilitySubsetFeaturesEXTX*)next;
enableFeatures(&_enabledPortabilityFeatures.triangleFans,
&requestedFeatures->triangleFans,
&pdPortabilityFeatures.triangleFans, 5);
break;
}
default:
break;
}
next = (MVKVkAPIStructHeader*)next->pNext;
}
}
void MVKDevice::enableFeatures(const VkBool32* pEnable, const VkBool32* pRequested, const VkBool32* pAvailable, uint32_t count) {
for (uint32_t i = 0; i < count; i++) {
((VkBool32*)pEnable)[i] = pRequested[i] && pAvailable[i];
if (pRequested[i] && !pAvailable[i]) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateDevice(): Requested feature is not available on this device."));
}
}
}
void MVKDevice::enableExtensions(const VkDeviceCreateInfo* pCreateInfo) {
MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_enabledExtensions;
setConfigurationResult(pWritableExtns->enable(pCreateInfo->enabledExtensionCount,
pCreateInfo->ppEnabledExtensionNames,
getInstance()->getDriverLayer()->getSupportedExtensions()));
}
// Create the command queues // Create the command queues
void MVKDevice::initQueues(const VkDeviceCreateInfo* pCreateInfo) { void MVKDevice::initQueues(const VkDeviceCreateInfo* pCreateInfo) {
vector<MVKQueueFamily*> qFams = _physicalDevice->getQueueFamilies(); vector<MVKQueueFamily*> qFams = _physicalDevice->getQueueFamilies();

View File

@ -226,7 +226,7 @@ void MVKGraphicsPipeline::encode(MVKCommandEncoder* cmdEncoder, uint32_t stage)
[mtlCmdEnc setFrontFacingWinding: _mtlFrontWinding]; [mtlCmdEnc setFrontFacingWinding: _mtlFrontWinding];
[mtlCmdEnc setTriangleFillMode: _mtlFillMode]; [mtlCmdEnc setTriangleFillMode: _mtlFillMode];
if (_device->_pFeatures->depthClamp) { if (_device->_enabledFeatures.depthClamp) {
[mtlCmdEnc setDepthClipMode: _mtlDepthClipMode]; [mtlCmdEnc setDepthClipMode: _mtlDepthClipMode];
} }
@ -323,7 +323,7 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
_mtlFrontWinding = mvkMTLWindingFromVkFrontFace(_rasterInfo.frontFace); _mtlFrontWinding = mvkMTLWindingFromVkFrontFace(_rasterInfo.frontFace);
_mtlFillMode = mvkMTLTriangleFillModeFromVkPolygonMode(_rasterInfo.polygonMode); _mtlFillMode = mvkMTLTriangleFillModeFromVkPolygonMode(_rasterInfo.polygonMode);
if (_rasterInfo.depthClampEnable) { if (_rasterInfo.depthClampEnable) {
if (_device->_pFeatures->depthClamp) { if (_device->_enabledFeatures.depthClamp) {
_mtlDepthClipMode = MTLDepthClipModeClamp; _mtlDepthClipMode = MTLDepthClipModeClamp;
} else { } else {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "This device does not support depth clamping.")); setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "This device does not support depth clamping."));

View File

@ -244,7 +244,7 @@ MVKOcclusionQueryPool::~MVKOcclusionQueryPool() {
MVKPipelineStatisticsQueryPool::MVKPipelineStatisticsQueryPool(MVKDevice* device, MVKPipelineStatisticsQueryPool::MVKPipelineStatisticsQueryPool(MVKDevice* device,
const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1) { const VkQueryPoolCreateInfo* pCreateInfo) : MVKQueryPool(device, pCreateInfo, 1) {
if ( !_device->_pFeatures->pipelineStatisticsQuery ) { if ( !_device->_enabledFeatures.pipelineStatisticsQuery ) {
setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateQueryPool: VK_QUERY_TYPE_PIPELINE_STATISTICS is not supported.")); setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateQueryPool: VK_QUERY_TYPE_PIPELINE_STATISTICS is not supported."));
} }
} }

View File

@ -159,7 +159,7 @@ MVK_PUBLIC_SYMBOL VkResult vkCreateDevice(
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice); MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
MVKDevice* mvkDev = new MVKDevice(mvkPD, pCreateInfo); MVKDevice* mvkDev = new MVKDevice(mvkPD, pCreateInfo);
*pDevice = mvkDev->getVkDevice(); *pDevice = mvkDev->getVkDevice();
return VK_SUCCESS; return mvkDev->getConfigurationResult();
} }
MVK_PUBLIC_SYMBOL void vkDestroyDevice( MVK_PUBLIC_SYMBOL void vkDestroyDevice(
@ -288,12 +288,14 @@ MVK_PUBLIC_SYMBOL VkResult vkFlushMappedMemoryRanges(
uint32_t memRangeCount, uint32_t memRangeCount,
const VkMappedMemoryRange* pMemRanges) { const VkMappedMemoryRange* pMemRanges) {
VkResult rslt = VK_SUCCESS;
for (uint32_t i = 0; i < memRangeCount; i++) { for (uint32_t i = 0; i < memRangeCount; i++) {
const VkMappedMemoryRange* pMem = &pMemRanges[i]; const VkMappedMemoryRange* pMem = &pMemRanges[i];
MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)pMem->memory; MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)pMem->memory;
mvkMem->flushToDevice(pMem->offset, pMem->size); VkResult r = mvkMem->flushToDevice(pMem->offset, pMem->size);
if (rslt == VK_SUCCESS) { rslt = r; }
} }
return VK_SUCCESS; return rslt;
} }
MVK_PUBLIC_SYMBOL VkResult vkInvalidateMappedMemoryRanges( MVK_PUBLIC_SYMBOL VkResult vkInvalidateMappedMemoryRanges(
@ -301,12 +303,14 @@ MVK_PUBLIC_SYMBOL VkResult vkInvalidateMappedMemoryRanges(
uint32_t memRangeCount, uint32_t memRangeCount,
const VkMappedMemoryRange* pMemRanges) { const VkMappedMemoryRange* pMemRanges) {
VkResult rslt = VK_SUCCESS;
for (uint32_t i = 0; i < memRangeCount; i++) { for (uint32_t i = 0; i < memRangeCount; i++) {
const VkMappedMemoryRange* pMem = &pMemRanges[i]; const VkMappedMemoryRange* pMem = &pMemRanges[i];
MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)pMem->memory; MVKDeviceMemory* mvkMem = (MVKDeviceMemory*)pMem->memory;
mvkMem->pullFromDevice(pMem->offset, pMem->size); VkResult r = mvkMem->pullFromDevice(pMem->offset, pMem->size);
if (rslt == VK_SUCCESS) { rslt = r; }
} }
return VK_SUCCESS; return rslt;
} }
MVK_PUBLIC_SYMBOL void vkGetDeviceMemoryCommitment( MVK_PUBLIC_SYMBOL void vkGetDeviceMemoryCommitment(
@ -366,7 +370,10 @@ MVK_PUBLIC_SYMBOL void vkGetImageSparseMemoryRequirements(
uint32_t* pNumRequirements, uint32_t* pNumRequirements,
VkSparseImageMemoryRequirements* pSparseMemoryRequirements) { VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
MVKLogUnimplemented("vkGetImageSparseMemoryRequirements"); // Metal does not support sparse images.
// Vulkan spec: "If the image was not created with VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT then
// pSparseMemoryRequirementCount will be set to zero and pSparseMemoryRequirements will not be written to.".
*pNumRequirements = 0; *pNumRequirements = 0;
} }
@ -380,7 +387,10 @@ MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceSparseImageFormatProperties(
uint32_t* pPropertyCount, uint32_t* pPropertyCount,
VkSparseImageFormatProperties* pProperties) { VkSparseImageFormatProperties* pProperties) {
MVKLogUnimplemented("vkGetPhysicalDeviceSparseImageFormatProperties"); // Metal does not support sparse images.
// Vulkan spec: "If VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT is not supported for the given arguments,
// pPropertyCount will be set to zero upon return, and no data will be written to pProperties.".
*pPropertyCount = 0; *pPropertyCount = 0;
} }
@ -390,7 +400,7 @@ MVK_PUBLIC_SYMBOL VkResult vkQueueBindSparse(
const VkBindSparseInfo* pBindInfo, const VkBindSparseInfo* pBindInfo,
VkFence fence) { VkFence fence) {
return MVKLogUnimplemented("vkQueueBindSparse"); return mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkQueueBindSparse(): Sparse binding is not supported.");
} }
MVK_PUBLIC_SYMBOL VkResult vkCreateFence( MVK_PUBLIC_SYMBOL VkResult vkCreateFence(
@ -1569,7 +1579,10 @@ MVK_PUBLIC_SYMBOL void vkGetImageSparseMemoryRequirements2KHR(
uint32_t* pSparseMemoryRequirementCount, uint32_t* pSparseMemoryRequirementCount,
VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements) { VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements) {
MVKLogUnimplemented("vkGetImageSparseMemoryRequirements2KHR"); // Metal does not support sparse images.
// Vulkan spec: "If the image was not created with VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT then
// pSparseMemoryRequirementCount will be set to zero and pSparseMemoryRequirements will not be written to.".
*pSparseMemoryRequirementCount = 0; *pSparseMemoryRequirementCount = 0;
} }
@ -1634,7 +1647,10 @@ MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
uint32_t* pPropertyCount, uint32_t* pPropertyCount,
VkSparseImageFormatProperties2KHR* pProperties) { VkSparseImageFormatProperties2KHR* pProperties) {
MVKLogUnimplemented("vkGetPhysicalDeviceSparseImageFormatProperties"); // Metal does not support sparse images.
// Vulkan spec: "If VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT is not supported for the given arguments,
// pPropertyCount will be set to zero upon return, and no data will be written to pProperties.".
*pPropertyCount = 0; *pPropertyCount = 0;
} }