Skip to content

Commit

Permalink
Add: KHR_maintenance4
Browse files Browse the repository at this point in the history
  • Loading branch information
spnda committed Jan 6, 2024
1 parent d20d13f commit 3fb74dc
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 40 deletions.
2 changes: 1 addition & 1 deletion MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class MVKBuffer : public MVKResource {

/** Returns the memory requirements of this resource by populating the specified structure. */
VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements);

/** Binds this resource to the specified offset within the specified memory allocation. */
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;

Expand Down
4 changes: 2 additions & 2 deletions MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@
// Multiple rows will automatically align with PoT max texture dimension, but need to align upwards if less than full single row.
size_t maxBlocksPerRow = _device->_pMetalFeatures->maxTextureDimension / fmtBlockSize.width;
size_t blocksPerRow = min(blockCount, maxBlocksPerRow);
_mtlBytesPerRow = mvkAlignByteCount(blocksPerRow * bytesPerBlock, _device->getVkFormatTexelBufferAlignment(pCreateInfo->format, this));
_mtlBytesPerRow = mvkAlignByteCount(blocksPerRow * bytesPerBlock, _device->getVkFormatTexelBufferAlignment(pCreateInfo->format));

size_t rowCount = blockCount / blocksPerRow;
if (blockCount % blocksPerRow) { rowCount++; }
Expand All @@ -358,7 +358,7 @@
// We can just use a simple 1D texel array.
_textureSize.width = uint32_t(blockCount * fmtBlockSize.width);
_textureSize.height = 1;
_mtlBytesPerRow = mvkAlignByteCount(byteCount, _device->getVkFormatTexelBufferAlignment(pCreateInfo->format, this));
_mtlBytesPerRow = mvkAlignByteCount(byteCount, _device->getVkFormatTexelBufferAlignment(pCreateInfo->format));
}

if ( !_device->_pMetalFeatures->texelBuffers ) {
Expand Down
2 changes: 1 addition & 1 deletion MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject {
uint32_t getMetalBufferIndexForVertexAttributeBinding(uint32_t binding);

/** Returns the memory alignment required for the format when used in a texel buffer. */
VkDeviceSize getVkFormatTexelBufferAlignment(VkFormat format, MVKBaseObject* mvkObj);
VkDeviceSize getVkFormatTexelBufferAlignment(VkFormat format);

/**
* Returns the MTLBuffer used to hold occlusion query results,
Expand Down
14 changes: 12 additions & 2 deletions MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@
inlineUniformBlockFeatures->descriptorBindingInlineUniformBlockUpdateAfterBind = true;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES: {
auto* maintenace4Features = (VkPhysicalDeviceMaintenance4Features*)next;
maintenace4Features->maintenance4 = true;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
auto* multiviewFeatures = (VkPhysicalDeviceMultiviewFeatures*)next;
multiviewFeatures->multiview = supportedFeats11.multiview;
Expand Down Expand Up @@ -645,7 +650,11 @@
maint3Props->maxMemoryAllocationSize = supportedProps11.maxMemoryAllocationSize;
break;
}

case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES: {
auto* maintenance4Props = (VkPhysicalDeviceMaintenance4Properties*)next;
maintenance4Props->maxBufferSize = _metalFeatures.maxMTLBufferSize;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES: {
auto* depthStencilResolveProps = (VkPhysicalDeviceDepthStencilResolveProperties*)next;
depthStencilResolveProps->supportedDepthResolveModes = supportedProps12.supportedDepthResolveModes;
Expand Down Expand Up @@ -3730,6 +3739,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope
*pMaxDeviation = cpuEnd - cpuStart;
}


#pragma mark Object lifecycle

uint32_t MVKDevice::getVulkanMemoryTypeIndex(MTLStorageMode mtlStorageMode) {
Expand Down Expand Up @@ -4488,7 +4498,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope
return ((_pMetalFeatures->maxPerStageBufferCount - 1) - binding);
}

VkDeviceSize MVKDevice::getVkFormatTexelBufferAlignment(VkFormat format, MVKBaseObject* mvkObj) {
VkDeviceSize MVKDevice::getVkFormatTexelBufferAlignment(VkFormat format) {
VkDeviceSize deviceAlignment = 0;
id<MTLDevice> mtlDev = getMTLDevice();
MVKPixelFormats* mvkPixFmts = getPixelFormats();
Expand Down
29 changes: 17 additions & 12 deletions MoltenVK/MoltenVK/GPUObjects/MVKImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ class MVKImage : public MVKVulkanAPIDeviceObject {
/** Returns the 3D extent of this image at the specified mipmap level. */
VkExtent3D getExtent3D(uint8_t planeIndex = 0, uint32_t mipLevel = 0);

/** Returns the 3D extent of this image at the specified mipmap level. */
static VkExtent3D getExtent3D(VkExtent3D extent, VkExtent2D blockTexelSize, bool hasChromaSubsampling, uint32_t mipLevel = 0);

/** Returns the number of mipmap levels in this image. */
uint32_t getMipLevelCount() { return _mipLevels; }

Expand All @@ -200,22 +203,22 @@ class MVKImage : public MVKVulkanAPIDeviceObject {
/** Returns the number of samples for each pixel of this image. */
VkSampleCountFlagBits getSampleCount() { return _samples; }

/**
* Returns the number of bytes per image row at the specified zero-based mip level.
* For non-compressed formats, this is the number of bytes in a row of texels.
* For compressed formats, this is the number of bytes in a row of blocks, which
* will typically span more than one row of texels.
*/
VkDeviceSize getBytesPerRow(uint8_t planeIndex, uint32_t mipLevel);

/**
* Returns the number of bytes per image row for the mip with the given width.
* For non-compressed formats, this is the number of bytes in a row of texels.
* For compressed formats, this is the number of bytes in a row of blocks, which
* will typically span more than one row of texels.
*/
VkDeviceSize getBytesPerRow(MTLPixelFormat planePixelFormat, uint32_t mipWidth);
/**
* Returns the number of bytes per image layer (for cube, array, or 3D images)
* at the specified zero-based mip level. This value will normally be the number
* of bytes per row (as returned by the getBytesPerRow() function, multiplied by
* for the mip with the given extent. This value will normally be the number
* of bytes per row (as returned by the getBytesPerRow() function, multiplied by
* the height of each 2D image.
*/
VkDeviceSize getBytesPerLayer(uint8_t planeIndex, uint32_t mipLevel);
VkDeviceSize getBytesPerLayer(uint8_t planeIndex, VkExtent3D mipExtent);
/** Returns the number of planes of this image view. */
uint8_t getPlaneCount() { return _planes.size(); }

Expand All @@ -237,6 +240,8 @@ class MVKImage : public MVKVulkanAPIDeviceObject {

/** Returns the memory requirements of this resource by populating the specified structure. */
VkResult getMemoryRequirements(const void* pInfo, VkMemoryRequirements2* pMemoryRequirements);

VkResult getMemoryRequirements(VkMemoryRequirements2* pMemoryRequirements, uint8_t planeIndex);

/** Binds this resource to the specified offset within the specified memory allocation. */
virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset, uint8_t planeIndex);
Expand Down
45 changes: 28 additions & 17 deletions MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@

for (uint32_t mipLvl = 0; mipLvl < _image->_mipLevels; mipLvl++) {
subRez.subresource.mipLevel = mipLvl;
VkDeviceSize rowPitch = _image->getBytesPerRow(_planeIndex, mipLvl);
VkDeviceSize depthPitch = _image->getBytesPerLayer(_planeIndex, mipLvl);

VkExtent3D mipExtent = _image->getExtent3D(_planeIndex, mipLvl);
VkExtent3D mipExtent = _image->getExtent3D(_planeIndex, mipLvl);
auto planeMTLPixFmt = _image->getPixelFormats()->getChromaSubsamplingPlaneMTLPixelFormat(_image->_vkFormat, _planeIndex);
VkDeviceSize rowPitch = _image->getBytesPerRow(planeMTLPixFmt, mipExtent.width);
VkDeviceSize depthPitch = _image->getPixelFormats()->getBytesPerLayer(planeMTLPixFmt, rowPitch, mipExtent.height);

for (uint32_t layer = 0; layer < _image->_arrayLayers; layer++) {
subRez.subresource.arrayLayer = layer;
Expand Down Expand Up @@ -575,17 +575,23 @@
return mvkMipmapLevelSizeFromBaseSize3D(extent, mipLevel);
}

VkDeviceSize MVKImage::getBytesPerRow(uint8_t planeIndex, uint32_t mipLevel) {
MTLPixelFormat planeMTLPixFmt = getPixelFormats()->getChromaSubsamplingPlaneMTLPixelFormat(_vkFormat, planeIndex);
size_t bytesPerRow = getPixelFormats()->getBytesPerRow(planeMTLPixFmt, getExtent3D(planeIndex, mipLevel).width);
VkExtent3D MVKImage::getExtent3D(VkExtent3D extent, VkExtent2D blockTexelSize, bool hasChromaSubsampling, uint32_t mipLevel) {
if (hasChromaSubsampling) {
extent.width /= blockTexelSize.width;
extent.height /= blockTexelSize.height;
}
return mvkMipmapLevelSizeFromBaseSize3D(extent, mipLevel);
}

VkDeviceSize MVKImage::getBytesPerRow(MTLPixelFormat planePixelFormat, uint32_t mipWidth) {
size_t bytesPerRow = getPixelFormats()->getBytesPerRow(planePixelFormat, mipWidth);
return mvkAlignByteCount(bytesPerRow, _rowByteAlignment);
}

VkDeviceSize MVKImage::getBytesPerLayer(uint8_t planeIndex, uint32_t mipLevel) {
MTLPixelFormat planeMTLPixFmt = getPixelFormats()->getChromaSubsamplingPlaneMTLPixelFormat(_vkFormat, planeIndex);
VkExtent3D extent = getExtent3D(planeIndex, mipLevel);
size_t bytesPerRow = getBytesPerRow(planeIndex, mipLevel);
return getPixelFormats()->getBytesPerLayer(planeMTLPixFmt, bytesPerRow, extent.height);
VkDeviceSize MVKImage::getBytesPerLayer(uint8_t planeIndex, VkExtent3D mipExtent) {
MTLPixelFormat planeMTLPixFmt = getPixelFormats()->getChromaSubsamplingPlaneMTLPixelFormat(_vkFormat, planeIndex);
VkDeviceSize bytesPerRow = getBytesPerRow(planeMTLPixFmt, mipExtent.width);
return getPixelFormats()->getBytesPerLayer(planeMTLPixFmt, bytesPerRow, mipExtent.height);
}

VkResult MVKImage::getSubresourceLayout(const VkImageSubresource* pSubresource,
Expand Down Expand Up @@ -618,7 +624,6 @@
return _viewFormats.empty();
}


#pragma mark Resource memory

void MVKImage::applyImageMemoryBarrier(MVKPipelineBarrier& barrier,
Expand Down Expand Up @@ -672,6 +677,12 @@
return _memoryBindings[planeIndex]->getMemoryRequirements(pInfo, pMemoryRequirements);
}

VkResult MVKImage::getMemoryRequirements(VkMemoryRequirements2 *pMemoryRequirements, uint8_t planeIndex) {
VkResult rslt = getMemoryRequirements(&pMemoryRequirements->memoryRequirements, planeIndex);
if (rslt != VK_SUCCESS) { return rslt; }
return _memoryBindings[planeIndex]->getMemoryRequirements(nullptr, pMemoryRequirements);
}

VkResult MVKImage::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset, uint8_t planeIndex) {
return _memoryBindings[planeIndex]->bindDeviceMemory(mvkMem, memOffset);
}
Expand Down Expand Up @@ -933,7 +944,7 @@
_isDepthStencilAttachment = (mvkAreAllFlagsEnabled(pCreateInfo->usage, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ||
mvkAreAllFlagsEnabled(pixFmts->getVkFormatProperties3(pCreateInfo->format).optimalTilingFeatures, VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT));
_canSupportMTLTextureView = !_isDepthStencilAttachment || _device->_pMetalFeatures->stencilViews;
_rowByteAlignment = _isLinear || _isLinearForAtomics ? _device->getVkFormatTexelBufferAlignment(pCreateInfo->format, this) : mvkEnsurePowerOfTwo(pixFmts->getBytesPerBlock(pCreateInfo->format));
_rowByteAlignment = _isLinear || _isLinearForAtomics ? _device->getVkFormatTexelBufferAlignment(pCreateInfo->format) : mvkEnsurePowerOfTwo(pixFmts->getBytesPerBlock(pCreateInfo->format));

VkExtent2D blockTexelSizeOfPlane[3];
uint32_t bytesPerBlockOfPlane[3];
Expand Down Expand Up @@ -970,15 +981,15 @@
NSUInteger bufferLength = 0;
for (uint32_t mipLvl = 0; mipLvl < _mipLevels; mipLvl++) {
VkExtent3D mipExtent = getExtent3D(planeIndex, mipLvl);
bufferLength += getBytesPerLayer(planeIndex, mipLvl) * mipExtent.depth * _arrayLayers;
bufferLength += getBytesPerLayer(planeIndex, mipExtent) * mipExtent.depth * _arrayLayers;
}
MTLSizeAndAlign sizeAndAlign = [_device->getMTLDevice() heapBufferSizeAndAlignWithLength: bufferLength options: MTLResourceStorageModePrivate];
memoryBinding->_byteCount += sizeAndAlign.size;
memoryBinding->_byteCount = sizeAndAlign.size;
memoryBinding->_byteAlignment = std::max(std::max(memoryBinding->_byteAlignment, _rowByteAlignment), (VkDeviceSize)sizeAndAlign.align);
} else {
for (uint32_t mipLvl = 0; mipLvl < _mipLevels; mipLvl++) {
VkExtent3D mipExtent = getExtent3D(planeIndex, mipLvl);
memoryBinding->_byteCount += getBytesPerLayer(planeIndex, mipLvl) * mipExtent.depth * _arrayLayers;
memoryBinding->_byteCount += getBytesPerLayer(planeIndex, mipExtent) * mipExtent.depth * _arrayLayers;
}
memoryBinding->_byteAlignment = std::max(memoryBinding->_byteAlignment, _rowByteAlignment);
}
Expand Down
4 changes: 2 additions & 2 deletions MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1674,7 +1674,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3

shaderConfig.options.mslOptions.msl_version = _device->_pMetalFeatures->mslVersion;
shaderConfig.options.mslOptions.texel_buffer_texture_width = _device->_pMetalFeatures->maxTextureDimension;
shaderConfig.options.mslOptions.r32ui_linear_texture_alignment = (uint32_t)_device->getVkFormatTexelBufferAlignment(VK_FORMAT_R32_UINT, this);
shaderConfig.options.mslOptions.r32ui_linear_texture_alignment = (uint32_t)_device->getVkFormatTexelBufferAlignment(VK_FORMAT_R32_UINT);
shaderConfig.options.mslOptions.texture_buffer_native = _device->_pMetalFeatures->textureBuffers;

bool useMetalArgBuff = isUsingMetalArgumentBuffers();
Expand Down Expand Up @@ -2113,7 +2113,7 @@ static MTLVertexFormat mvkAdjustFormatVectorToSize(MTLVertexFormat format, uint3
shaderConfig.options.entryPointStage = spv::ExecutionModelGLCompute;
shaderConfig.options.mslOptions.msl_version = _device->_pMetalFeatures->mslVersion;
shaderConfig.options.mslOptions.texel_buffer_texture_width = _device->_pMetalFeatures->maxTextureDimension;
shaderConfig.options.mslOptions.r32ui_linear_texture_alignment = (uint32_t)_device->getVkFormatTexelBufferAlignment(VK_FORMAT_R32_UINT, this);
shaderConfig.options.mslOptions.r32ui_linear_texture_alignment = (uint32_t)_device->getVkFormatTexelBufferAlignment(VK_FORMAT_R32_UINT);
shaderConfig.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle;
shaderConfig.options.mslOptions.texture_buffer_native = _device->_pMetalFeatures->textureBuffers;
shaderConfig.options.mslOptions.dispatch_base = _allowsDispatchBase;
Expand Down
1 change: 1 addition & 0 deletions MoltenVK/MoltenVK/Layers/MVKExtensions.def
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ MVK_EXTENSION(KHR_incremental_present, KHR_INCREMENTAL_PRESENT,
MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(KHR_maintenance4, KHR_MAINTENANCE_4, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(KHR_map_memory2, KHR_MAP_MEMORY_2, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(KHR_multiview, KHR_MULTIVIEW, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(KHR_portability_subset, KHR_PORTABILITY_SUBSET, DEVICE, 10.11, 8.0, 1.0)
Expand Down
49 changes: 46 additions & 3 deletions MoltenVK/MoltenVK/Vulkan/vulkan.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2814,9 +2814,44 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkDestroyPrivateDataSlot(
MVKTraceVulkanCallEnd();
}

MVK_PUBLIC_VULKAN_STUB(vkGetDeviceBufferMemoryRequirements, void, VkDevice, const VkDeviceBufferMemoryRequirements*, VkMemoryRequirements2*)
MVK_PUBLIC_VULKAN_STUB(vkGetDeviceImageMemoryRequirements, void, VkDevice, const VkDeviceImageMemoryRequirements*, VkMemoryRequirements2*)
MVK_PUBLIC_VULKAN_STUB(vkGetDeviceImageSparseMemoryRequirements, void, VkDevice, const VkDeviceImageMemoryRequirements*, uint32_t*, VkSparseImageMemoryRequirements2*)
MVK_PUBLIC_VULKAN_SYMBOL void vkGetDeviceBufferMemoryRequirements(
VkDevice device,
const VkDeviceBufferMemoryRequirements* pInfo,
VkMemoryRequirements2* pMemoryRequirements) {

MVKTraceVulkanCallStart();
auto* mvkDev = MVKDevice::getMVKDevice(device);
auto* buffer = new MVKBuffer(mvkDev, pInfo->pCreateInfo);
buffer->getMemoryRequirements(nullptr, pMemoryRequirements);
buffer->destroy();
MVKTraceVulkanCallEnd();
}

MVK_PUBLIC_VULKAN_SYMBOL void vkGetDeviceImageMemoryRequirements(
VkDevice device,
const VkDeviceImageMemoryRequirements* pInfo,
VkMemoryRequirements2* pMemoryRequirements) {

MVKTraceVulkanCallStart();
auto* mvkDev = MVKDevice::getMVKDevice(device);
auto* image = new MVKImage(mvkDev, pInfo->pCreateInfo);
image->getMemoryRequirements(pMemoryRequirements, MVKImage::getPlaneFromVkImageAspectFlags(pInfo->planeAspect));
image->destroy();
MVKTraceVulkanCallEnd();
}

MVK_PUBLIC_VULKAN_SYMBOL void vkGetDeviceImageSparseMemoryRequirements(
VkDevice device,
const VkDeviceImageMemoryRequirements* pInfo,
uint32_t* pSparseMemoryRequirementCount,
VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {

MVKTraceVulkanCallStart();
// Metal does not support sparse images
*pSparseMemoryRequirementCount = 0;
MVKTraceVulkanCallEnd();
}

MVK_PUBLIC_VULKAN_STUB_VKRESULT(vkGetPhysicalDeviceToolProperties, VkPhysicalDevice, uint32_t*, VkPhysicalDeviceToolProperties*)

MVK_PUBLIC_VULKAN_SYMBOL void vkGetPrivateData(
Expand Down Expand Up @@ -3067,6 +3102,14 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkDestroyDeferredOperationKHR(
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkGetDescriptorSetLayoutSupport, KHR);


#pragma mark -
#pragma mark VK_KHR_maintenance4 extension

MVK_PUBLIC_VULKAN_CORE_ALIAS(vkGetDeviceBufferMemoryRequirements, KHR);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkGetDeviceImageMemoryRequirements, KHR);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkGetDeviceImageSparseMemoryRequirements, KHR);


#pragma mark -
#pragma mark VK_KHR_map_memory2 extension

Expand Down

0 comments on commit 3fb74dc

Please sign in to comment.