Add support for VK_EXT_private_data extension.
Moved to a new model for creation: create and potentially destroy the object within MVKDevice::create..., to hide it from vulkan.mm where all other object creation errors are handled. We could move to this slowly over time. Passes all 49 private data CTS tests.
This commit is contained in:
parent
7d6f68869c
commit
b71fe94558
@ -310,6 +310,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
|
||||
- `VK_EXT_memory_budget` *(requires Metal 2.0)*
|
||||
- `VK_EXT_metal_surface`
|
||||
- `VK_EXT_post_depth_coverage` *(iOS, requires GPU family 4)*
|
||||
- `VK_EXT_private_data `
|
||||
- `VK_EXT_robustness2`
|
||||
- `VK_EXT_scalar_block_layout`
|
||||
- `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)*
|
||||
|
@ -18,6 +18,8 @@ MoltenVK 1.1.1
|
||||
|
||||
Released TBD
|
||||
|
||||
- Add support for extensions:
|
||||
- `VK_EXT_private_data`
|
||||
- Use `VK_KHR_image_format_list` to disable `MTLTextureUsagePixelFormatView`
|
||||
if only swizzles or `sRGB` conversion will be used for image views, improving
|
||||
performance on *iOS* by allowing Metal to use lossless texture compression.
|
||||
|
@ -66,6 +66,7 @@ class MVKRenderPass;
|
||||
class MVKCommandPool;
|
||||
class MVKCommandEncoder;
|
||||
class MVKCommandResourceFactory;
|
||||
class MVKPrivateDataSlot;
|
||||
|
||||
|
||||
/** The buffer index to use for vertex content. */
|
||||
@ -578,6 +579,13 @@ public:
|
||||
void freeMemory(MVKDeviceMemory* mvkDevMem,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
VkResult createPrivateDataSlot(const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkPrivateDataSlotEXT* pPrivateDataSlot);
|
||||
|
||||
void destroyPrivateDataSlot(VkPrivateDataSlotEXT privateDataSlot,
|
||||
const VkAllocationCallbacks* pAllocator);
|
||||
|
||||
|
||||
#pragma mark Operations
|
||||
|
||||
@ -678,6 +686,7 @@ public:
|
||||
const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT _enabledScalarLayoutFeatures;
|
||||
const VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT _enabledTexelBuffAlignFeatures;
|
||||
const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT _enabledVtxAttrDivFeatures;
|
||||
const VkPhysicalDevicePrivateDataFeaturesEXT _enabledPrivateDataFeatures;
|
||||
const VkPhysicalDevicePortabilitySubsetFeaturesKHR _enabledPortabilityFeatures;
|
||||
|
||||
/** The list of Vulkan extensions, indicating whether each has been enabled by the app for this device. */
|
||||
@ -724,6 +733,7 @@ protected:
|
||||
void initPerformanceTracking();
|
||||
void initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo);
|
||||
void initQueues(const VkDeviceCreateInfo* pCreateInfo);
|
||||
void reservePrivateData(const VkDeviceCreateInfo* pCreateInfo);
|
||||
void initMTLCompileOptions();
|
||||
void enableFeatures(const VkDeviceCreateInfo* pCreateInfo);
|
||||
void enableFeatures(const VkBool32* pEnable, const VkBool32* pRequested, const VkBool32* pAvailable, uint32_t count);
|
||||
@ -737,6 +747,8 @@ protected:
|
||||
MTLCompileOptions* _mtlCompileOptions;
|
||||
MVKSmallVector<MVKSmallVector<MVKQueue*, kMVKQueueCountPerQueueFamily>, kMVKQueueFamilyCount> _queuesByQueueFamilyIndex;
|
||||
MVKSmallVector<MVKResource*, 256> _resources;
|
||||
MVKSmallVector<MVKPrivateDataSlot*> _privateDataSlots;
|
||||
MVKSmallVector<bool> _privateDataSlotsAvailability;
|
||||
std::mutex _rezLock;
|
||||
std::mutex _perfLock;
|
||||
id<MTLBuffer> _globalVisibilityResultMTLBuffer;
|
||||
@ -819,6 +831,35 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKPrivateDataSlot
|
||||
|
||||
/** Private data slot. */
|
||||
class MVKPrivateDataSlot : public MVKVulkanAPIDeviceObject {
|
||||
|
||||
public:
|
||||
|
||||
/** Returns the Vulkan type of this object. */
|
||||
VkObjectType getVkObjectType() override { return VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT; }
|
||||
|
||||
/** Returns the debug report object type of this object. */
|
||||
VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; }
|
||||
|
||||
void setData(VkObjectType objectType, uint64_t objectHandle, uint64_t data) { _privateData[objectHandle] = data; }
|
||||
|
||||
uint64_t getData(VkObjectType objectType, uint64_t objectHandle) { return _privateData[objectHandle]; }
|
||||
|
||||
void clearData() { _privateData.clear(); }
|
||||
|
||||
MVKPrivateDataSlot(MVKDevice* device) : MVKVulkanAPIDeviceObject(device) {}
|
||||
|
||||
protected:
|
||||
void propagateDebugName() override {}
|
||||
|
||||
std::unordered_map<uint64_t, uint64_t> _privateData;
|
||||
};
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKDeviceObjectPool
|
||||
|
||||
|
@ -169,6 +169,11 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
|
||||
divisorFeatures->vertexAttributeInstanceRateZeroDivisor = true;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
|
||||
auto* privateDataFeatures = (VkPhysicalDevicePrivateDataFeaturesEXT*)next;
|
||||
privateDataFeatures->privateData = true;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR: {
|
||||
auto* portabilityFeatures = (VkPhysicalDevicePortabilitySubsetFeaturesKHR*)next;
|
||||
portabilityFeatures->constantAlphaColorBlendFactors = true;
|
||||
@ -2886,6 +2891,47 @@ void MVKDevice::freeMemory(MVKDeviceMemory* mvkDevMem,
|
||||
if (mvkDevMem) { mvkDevMem->destroy(); }
|
||||
}
|
||||
|
||||
// Look for an available pre-reserved private data slot and return it's address if found.
|
||||
// Otherwise create a new instance and return it.
|
||||
VkResult MVKDevice::createPrivateDataSlot(const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkPrivateDataSlotEXT* pPrivateDataSlot) {
|
||||
MVKPrivateDataSlot* mvkPDS = nullptr;
|
||||
|
||||
size_t slotCnt = _privateDataSlots.size();
|
||||
for (size_t slotIdx = 0; slotIdx < slotCnt; slotIdx++) {
|
||||
if ( _privateDataSlotsAvailability[slotIdx] ) {
|
||||
_privateDataSlotsAvailability[slotIdx] = false;
|
||||
mvkPDS = _privateDataSlots[slotIdx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mvkPDS ) { mvkPDS = new MVKPrivateDataSlot(this); }
|
||||
|
||||
*pPrivateDataSlot = (VkPrivateDataSlotEXT)mvkPDS;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
// If the private data slot is one of the pre-reserved slots, clear it and mark it as available.
|
||||
// Otherwise destroy it.
|
||||
void MVKDevice::destroyPrivateDataSlot(VkPrivateDataSlotEXT privateDataSlot,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
|
||||
MVKPrivateDataSlot* mvkPDS = (MVKPrivateDataSlot*)privateDataSlot;
|
||||
|
||||
size_t slotCnt = _privateDataSlots.size();
|
||||
for (size_t slotIdx = 0; slotIdx < slotCnt; slotIdx++) {
|
||||
if (mvkPDS == _privateDataSlots[slotIdx]) {
|
||||
mvkPDS->clearData();
|
||||
_privateDataSlotsAvailability[slotIdx] = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mvkPDS->destroy();
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Operations
|
||||
|
||||
@ -3077,6 +3123,7 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
|
||||
_enabledScalarLayoutFeatures(),
|
||||
_enabledTexelBuffAlignFeatures(),
|
||||
_enabledVtxAttrDivFeatures(),
|
||||
_enabledPrivateDataFeatures(),
|
||||
_enabledPortabilityFeatures(),
|
||||
_enabledExtensions(this)
|
||||
{
|
||||
@ -3085,6 +3132,8 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
|
||||
initPhysicalDevice(physicalDevice, pCreateInfo);
|
||||
enableFeatures(pCreateInfo);
|
||||
enableExtensions(pCreateInfo);
|
||||
initQueues(pCreateInfo);
|
||||
reservePrivateData(pCreateInfo);
|
||||
|
||||
_globalVisibilityResultMTLBuffer = nil;
|
||||
_globalVisibilityQueryCount = 0;
|
||||
@ -3093,8 +3142,6 @@ MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo
|
||||
|
||||
_commandResourceFactory = new MVKCommandResourceFactory(this);
|
||||
|
||||
initQueues(pCreateInfo);
|
||||
|
||||
if (getInstance()->_autoGPUCaptureScope == MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_DEVICE) {
|
||||
MTLCaptureManager *captureMgr = [MTLCaptureManager sharedCaptureManager];
|
||||
if (!getInstance()->_autoGPUCaptureOutputFile.empty()) {
|
||||
@ -3225,6 +3272,7 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
|
||||
mvkClear(&_enabledScalarLayoutFeatures);
|
||||
mvkClear(&_enabledTexelBuffAlignFeatures);
|
||||
mvkClear(&_enabledVtxAttrDivFeatures);
|
||||
mvkClear(&_enabledPrivateDataFeatures);
|
||||
mvkClear(&_enabledPortabilityFeatures);
|
||||
|
||||
// Fetch the available physical device features.
|
||||
@ -3232,9 +3280,13 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
|
||||
pdPortabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR;
|
||||
pdPortabilityFeatures.pNext = NULL;
|
||||
|
||||
VkPhysicalDevicePrivateDataFeaturesEXT pdPrivateDataFeatures;
|
||||
pdPrivateDataFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT;
|
||||
pdPrivateDataFeatures.pNext = &pdPortabilityFeatures;
|
||||
|
||||
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT pdVtxAttrDivFeatures;
|
||||
pdVtxAttrDivFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
|
||||
pdVtxAttrDivFeatures.pNext = &pdPortabilityFeatures;
|
||||
pdVtxAttrDivFeatures.pNext = &pdPrivateDataFeatures;
|
||||
|
||||
VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT pdTexelBuffAlignFeatures;
|
||||
pdTexelBuffAlignFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT;
|
||||
@ -3375,6 +3427,13 @@ void MVKDevice::enableFeatures(const VkDeviceCreateInfo* pCreateInfo) {
|
||||
&pdVtxAttrDivFeatures.vertexAttributeInstanceRateDivisor, 2);
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
|
||||
auto* requestedFeatures = (VkPhysicalDevicePrivateDataFeaturesEXT*)next;
|
||||
enableFeatures(&_enabledPrivateDataFeatures.privateData,
|
||||
&requestedFeatures->privateData,
|
||||
&pdPrivateDataFeatures.privateData, 1);
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR: {
|
||||
auto* requestedFeatures = (VkPhysicalDevicePortabilitySubsetFeaturesKHR*)next;
|
||||
enableFeatures(&_enabledPortabilityFeatures.constantAlphaColorBlendFactors,
|
||||
@ -3428,6 +3487,28 @@ void MVKDevice::initQueues(const VkDeviceCreateInfo* pCreateInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
void MVKDevice::reservePrivateData(const VkDeviceCreateInfo* pCreateInfo) {
|
||||
size_t slotCnt = 0;
|
||||
for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
|
||||
switch (next->sType) {
|
||||
case VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT: {
|
||||
auto* pPDCreateInfo = (const VkDevicePrivateDataCreateInfoEXT*)next;
|
||||
slotCnt += pPDCreateInfo->privateDataSlotRequestCount;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_privateDataSlots.reserve(slotCnt);
|
||||
_privateDataSlotsAvailability.reserve(slotCnt);
|
||||
for (uint32_t slotIdx = 0; slotIdx < slotCnt; slotIdx++) {
|
||||
_privateDataSlots.push_back(new MVKPrivateDataSlot(this));
|
||||
_privateDataSlotsAvailability.push_back(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MVKDevice::initMTLCompileOptions() {
|
||||
_mtlCompileOptions = [MTLCompileOptions new]; // retained
|
||||
_mtlCompileOptions.languageVersion = _pMetalFeatures->mslVersionEnum;
|
||||
@ -3445,6 +3526,8 @@ MVKDevice::~MVKDevice() {
|
||||
if (getInstance()->_autoGPUCaptureScope == MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_DEVICE) {
|
||||
[[MTLCaptureManager sharedCaptureManager] stopCapture];
|
||||
}
|
||||
|
||||
mvkDestroyContainerContents(_privateDataSlots);
|
||||
}
|
||||
|
||||
|
||||
|
@ -669,6 +669,10 @@ void MVKInstance::initProcAddrs() {
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkCmdDebugMarkerInsertEXT, EXT_DEBUG_MARKER);
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkGetRefreshCycleDurationGOOGLE, GOOGLE_DISPLAY_TIMING);
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkGetPastPresentationTimingGOOGLE, GOOGLE_DISPLAY_TIMING);
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkCreatePrivateDataSlotEXT, EXT_PRIVATE_DATA);
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkDestroyPrivateDataSlotEXT, EXT_PRIVATE_DATA);
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkGetPrivateDataEXT, EXT_PRIVATE_DATA);
|
||||
ADD_DVC_EXT_ENTRY_POINT(vkSetPrivateDataEXT, EXT_PRIVATE_DATA);
|
||||
}
|
||||
|
||||
void MVKInstance::logVersions() {
|
||||
|
@ -88,6 +88,7 @@ MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, DEVICE)
|
||||
MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, DEVICE)
|
||||
MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, INSTANCE)
|
||||
MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, DEVICE)
|
||||
MVK_EXTENSION(EXT_private_data, EXT_PRIVATE_DATA, DEVICE)
|
||||
MVK_EXTENSION(EXT_robustness2, EXT_ROBUSTNESS_2, DEVICE)
|
||||
MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, DEVICE)
|
||||
MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, DEVICE)
|
||||
|
@ -2934,6 +2934,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetRefreshCycleDurationGOOGLE(
|
||||
VkDevice device,
|
||||
VkSwapchainKHR swapchain,
|
||||
VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
|
||||
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKSwapchain* mvkSwapchain = (MVKSwapchain*)swapchain;
|
||||
VkResult rslt = mvkSwapchain->getRefreshCycleDuration(pDisplayTimingProperties);
|
||||
@ -2946,6 +2947,7 @@ MVK_PUBLIC_SYMBOL VkResult vkGetPastPresentationTimingGOOGLE(
|
||||
VkSwapchainKHR swapchain,
|
||||
uint32_t* pPresentationTimingCount,
|
||||
VkPastPresentationTimingGOOGLE* pPresentationTimings) {
|
||||
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKSwapchain* mvkSwapchain = (MVKSwapchain*)swapchain;
|
||||
VkResult rslt = mvkSwapchain->getPastPresentationTiming(pPresentationTimingCount, pPresentationTimings);
|
||||
@ -2953,6 +2955,60 @@ MVK_PUBLIC_SYMBOL VkResult vkGetPastPresentationTimingGOOGLE(
|
||||
return rslt;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark VK_EXT_private_data extension
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkCreatePrivateDataSlotEXT(
|
||||
VkDevice device,
|
||||
const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
|
||||
const VkAllocationCallbacks* pAllocator,
|
||||
VkPrivateDataSlotEXT* pPrivateDataSlot) {
|
||||
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
|
||||
VkResult rslt = mvkDev->createPrivateDataSlot(pCreateInfo, pAllocator, pPrivateDataSlot);
|
||||
MVKTraceVulkanCallEnd();
|
||||
return rslt;
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL void vkDestroyPrivateDataSlotEXT(
|
||||
VkDevice device,
|
||||
VkPrivateDataSlotEXT privateDataSlot,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
|
||||
mvkDev->destroyPrivateDataSlot(privateDataSlot, pAllocator);
|
||||
MVKTraceVulkanCallEnd();
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkSetPrivateDataEXT(
|
||||
VkDevice device,
|
||||
VkObjectType objectType,
|
||||
uint64_t objectHandle,
|
||||
VkPrivateDataSlotEXT privateDataSlot,
|
||||
uint64_t data) {
|
||||
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKPrivateDataSlot* mvkPDS = (MVKPrivateDataSlot*)privateDataSlot;
|
||||
mvkPDS->setData(objectType, objectHandle, data);
|
||||
MVKTraceVulkanCallEnd();
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL void vkGetPrivateDataEXT(
|
||||
VkDevice device,
|
||||
VkObjectType objectType,
|
||||
uint64_t objectHandle,
|
||||
VkPrivateDataSlotEXT privateDataSlot,
|
||||
uint64_t* pData) {
|
||||
|
||||
MVKTraceVulkanCallStart();
|
||||
MVKPrivateDataSlot* mvkPDS = (MVKPrivateDataSlot*)privateDataSlot;
|
||||
*pData = mvkPDS->getData(objectType, objectHandle);
|
||||
MVKTraceVulkanCallEnd();
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark iOS & macOS surface extensions
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user