diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index 3b3b964c..6855b3a0 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -243,6 +243,7 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following - `VK_KHR_swapchain` - `VK_KHR_swapchain_mutable_format` - `VK_KHR_variable_pointers` +- `VK_EXT_memory_budget` - `VK_EXT_shader_viewport_index_layer` - `VK_EXT_vertex_attribute_divisor` - `VK_EXTX_portability_subset` diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 39eeadb6..2f1a9274 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -210,7 +210,7 @@ public: VkResult getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties); /** Populates the specified memory properties with the memory characteristics of this device. */ - VkResult getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties); + VkResult getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties); /** * Returns a bit mask of all memory type indices. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 0049e43a..fc452c43 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -165,7 +165,7 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { break; } default: - next = (MVKVkAPIStructHeader*)((VkPhysicalDeviceProperties2*)next)->pNext; + next = (MVKVkAPIStructHeader*)next->pNext; break; } } @@ -612,10 +612,29 @@ VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMe return VK_SUCCESS; } -VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties) { +VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties) { if (pMemoryProperties) { - pMemoryProperties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR; + pMemoryProperties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; pMemoryProperties->memoryProperties = _memoryProperties; + auto* next = (MVKVkAPIStructHeader*)pMemoryProperties->pNext; + while (next) { + switch ((uint32_t)next->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: { + auto* budgetProps = (VkPhysicalDeviceMemoryBudgetPropertiesEXT*)next; + memset(budgetProps->heapBudget, 0, sizeof(budgetProps->heapBudget)); + memset(budgetProps->heapUsage, 0, sizeof(budgetProps->heapUsage)); + budgetProps->heapBudget[0] = (VkDeviceSize)mvkRecommendedMaxWorkingSetSize(_mtlDevice); + if ( [_mtlDevice respondsToSelector: @selector(currentAllocatedSize)] ) { + budgetProps->heapUsage[0] = (VkDeviceSize)_mtlDevice.currentAllocatedSize; + } + next = (MVKVkAPIStructHeader*)budgetProps->pNext; + break; + } + default: + next = (MVKVkAPIStructHeader*)next->pNext; + break; + } + } } return VK_SUCCESS; } diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp index 7c821cbb..0b531e64 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.cpp @@ -18,6 +18,7 @@ #include "MVKExtensions.h" #include "MVKFoundation.h" +#include "MVKOSExtensions.h" #include "vk_mvk_moltenvk.h" #include #include @@ -103,11 +104,17 @@ string MVKExtensionList::enabledNamesString(const char* separator, bool prefixFi // Returns whether the specified properties are valid for this platform static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { #if !(MVK_IOS) + if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { + return mvkOSVersion() >= 10.13; + } if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; } if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; } #endif #if !(MVK_MACOS) if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; } + if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { + return mvkOSVersion() >= 11.0; + } if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; } #endif diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 8c12a568..74b4c29b 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -51,6 +51,7 @@ MVK_EXTENSION(KHR_surface, KHR_SURFACE) MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN) MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT) MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS) +MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET) MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER) MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR) MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET) diff --git a/MoltenVK/MoltenVK/OS/MVKOSExtensions.h b/MoltenVK/MoltenVK/OS/MVKOSExtensions.h index 53a8ae73..a2e97e56 100644 --- a/MoltenVK/MoltenVK/OS/MVKOSExtensions.h +++ b/MoltenVK/MoltenVK/OS/MVKOSExtensions.h @@ -22,7 +22,9 @@ #include "MVKFoundation.h" #include +#ifdef __OBJC__ #import +#endif typedef float MVKOSVersion; @@ -59,6 +61,7 @@ double mvkGetTimestampPeriod(); */ double mvkGetElapsedMilliseconds(uint64_t startTimestamp = 0, uint64_t endTimestamp = 0); +#ifdef __OBJC__ /** Ensures the block is executed on the main thread. */ inline void mvkDispatchToMainAndWait(dispatch_block_t block) { if (NSThread.isMainThread) { @@ -67,12 +70,14 @@ inline void mvkDispatchToMainAndWait(dispatch_block_t block) { dispatch_sync(dispatch_get_main_queue(), block); } } +#endif #pragma mark - #pragma mark Process environment +#ifdef __OBJC__ /** * Returns the value of the environment variable at the given name, * or an empty string if no environment variable with that name exists. @@ -130,11 +135,13 @@ inline bool mvkGetEnvVarBool(std::string varName, bool* pWasFound = nullptr) { int64_t val = wasFound ? ev : EV; \ cfgVal = (int32_t)mvkClamp(val, (int64_t)INT32_MIN, (int64_t)INT32_MAX); \ } while(false) +#endif #pragma mark - #pragma mark MTLDevice +#ifdef __OBJC__ /** Returns an approximation of how much memory, in bytes, the device can use with good performance. */ uint64_t mvkRecommendedMaxWorkingSetSize(id mtlDevice); @@ -147,3 +154,4 @@ void mvkPopulateGPUInfo(VkPhysicalDeviceProperties& devProps, id mtlD * The format must support linear texture memory (must not be depth, stencil, or compressed). */ VkDeviceSize mvkMTLPixelFormatLinearTextureAlignment(MTLPixelFormat mtlPixelFormat, id mtlDevice); +#endif