From cef610ee141638384ebff21e701bc80346bb4d86 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Tue, 2 Oct 2018 16:22:34 -0500 Subject: [PATCH] MVKSampler: Support border colors. In Metal 1.2 on Mac, the `MTLSamplerAddressModeClampToBorderColor` address mode was added. This mode actually lets clients specify the border color, instead of hardcoding it to black (opaque without alpha, transparent with alpha). Use this new mode instead of `MTLSamplerAddressModeClampToZero` when possible. --- MoltenVK/MoltenVK/API/mvk_datatypes.h | 8 ++++++++ MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 3 ++- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 1 + MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 14 ++++++++++++++ .../MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.h | 9 +++++++++ .../MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m | 13 +++++++++++++ MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm | 14 ++++++++++++++ 7 files changed, 61 insertions(+), 1 deletion(-) diff --git a/MoltenVK/MoltenVK/API/mvk_datatypes.h b/MoltenVK/MoltenVK/API/mvk_datatypes.h index b21ba9ae..b638b02b 100644 --- a/MoltenVK/MoltenVK/API/mvk_datatypes.h +++ b/MoltenVK/MoltenVK/API/mvk_datatypes.h @@ -295,6 +295,14 @@ VkExtent3D mvkMipmapBaseSizeFromLevelSize3D(VkExtent3D levelSize, uint32_t level */ MTLSamplerAddressMode mvkMTLSamplerAddressModeFromVkSamplerAddressMode(VkSamplerAddressMode vkMode); +#if MVK_MACOS +/** + * Returns the Metal MTLSamplerBorderColor corresponding to the specified Vulkan VkBorderColor, + * or returns MTLSamplerBorderColorTransparentBlack if no corresponding MTLSamplerBorderColor exists. + */ +MTLSamplerBorderColor mvkMTLSamplerBorderColorFromVkBorderColor(VkBorderColor vkColor); +#endif + /** * Returns the Metal MTLSamplerMinMagFilter corresponding to the specified Vulkan VkFilter, * or returns MTLSamplerMinMagFilterNearest if no corresponding MTLSamplerMinMagFilter exists. diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index ccd9b6a8..467012c8 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -54,7 +54,7 @@ extern "C" { #define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH) -#define VK_MVK_MOLTENVK_SPEC_VERSION 12 +#define VK_MVK_MOLTENVK_SPEC_VERSION 13 #define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk" /** @@ -261,6 +261,7 @@ typedef struct { VkBool32 presentModeImmediate; /**< If true, immediate surface present mode (VK_PRESENT_MODE_IMMEDIATE_KHR), allowing a swapchain image to be presented immediately, without waiting for the vertical sync period of the display, is supported. */ VkBool32 stencilViews; /**< If true, stencil aspect views are supported through the MTLPixelFormatX24_Stencil8 and MTLPixelFormatX32_Stencil8 formats. */ VkBool32 multisampleArrayTextures; /**< If true, MTLTextureType2DMultisampleArray is supported. */ + VkBool32 samplerClampToBorder; /**< If true, the border color set when creating a sampler will be respected. */ uint32_t maxTextureDimension; /**< The maximum size of each texture dimension (width, height, or depth). */ uint32_t maxPerStageBufferCount; /**< The total number of per-stage Metal buffers available for shader uniform content and attributes. */ uint32_t maxPerStageTextureCount; /**< The total number of per-stage Metal textures available for shader uniform content. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 384bff85..625dda8a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -562,6 +562,7 @@ void MVKPhysicalDevice::initMetalFeatures() { _metalFeatures.dynamicMTLBuffers = true; _metalFeatures.shaderSpecialization = true; _metalFeatures.stencilViews = true; + _metalFeatures.samplerClampToBorder = true; _metalFeatures.maxMTLBufferSize = (1 * GIBI); } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 5d3b1285..5c311299 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -931,6 +931,20 @@ MTLSamplerDescriptor* MVKSampler::getMTLSamplerDescriptor(const VkSamplerCreateI mtlSampDesc.compareFunctionMVK = (pCreateInfo->compareEnable ? mvkMTLCompareFunctionFromVkCompareOp(pCreateInfo->compareOp) : MTLCompareFunctionNever); +#if MVK_MACOS + mtlSampDesc.borderColorMVK = mvkMTLSamplerBorderColorFromVkBorderColor(pCreateInfo->borderColor); + if (_device->getPhysicalDevice()->getMetalFeatures()->samplerClampToBorder) { + if (pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) { + mtlSampDesc.sAddressMode = MTLSamplerAddressModeClampToBorderColor; + } + if (pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) { + mtlSampDesc.tAddressMode = MTLSamplerAddressModeClampToBorderColor; + } + if (pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) { + mtlSampDesc.rAddressMode = MTLSamplerAddressModeClampToBorderColor; + } + } +#endif return [mtlSampDesc autorelease]; } diff --git a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.h b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.h index ee55dcd8..01feefea 100644 --- a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.h +++ b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.h @@ -32,4 +32,13 @@ */ @property(nonatomic, readwrite) MTLCompareFunction compareFunctionMVK; +/** + * Replacement for the borderColor property. + * + * This property allows support under all OS versions. Delegates to the borderColor + * property if it is available. otherwise, returns MTLSamplerBorderColorTransparentBlack when read and + * does nothing when set. + */ +@property(nonatomic, readwrite) /*MTLSamplerBorderColor*/ NSUInteger borderColorMVK; + @end diff --git a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m index 87c6ea08..4f02de6d 100644 --- a/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m +++ b/MoltenVK/MoltenVK/OS/MTLSamplerDescriptor+MoltenVK.m @@ -30,4 +30,17 @@ if ( [self respondsToSelector: @selector(setCompareFunction:)] ) { self.compareFunction = cmpFunc; } } +-(NSUInteger) borderColorMVK { +#if MVK_MACOS + if ( [self respondsToSelector: @selector(borderColor)] ) { return self.borderColor; } +#endif + return /*MTLSamplerBorderColorTransparentBlack*/ 0; +} + +-(void) setBorderColorMVK: (NSUInteger) color { +#if MVK_MACOS + if ( [self respondsToSelector: @selector(setBorderColor:)] ) { self.borderColor = (MTLSamplerBorderColor) color; } +#endif +} + @end diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm index d6505385..b844848a 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm @@ -941,6 +941,20 @@ MVK_PUBLIC_SYMBOL MTLSamplerAddressMode mvkMTLSamplerAddressModeFromVkSamplerAdd } } +#if MVK_MACOS +MVK_PUBLIC_SYMBOL MTLSamplerBorderColor mvkMTLSamplerBorderColorFromVkBorderColor(VkBorderColor vkColor) { + switch (vkColor) { + case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: return MTLSamplerBorderColorTransparentBlack; + case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: return MTLSamplerBorderColorTransparentBlack; + case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: return MTLSamplerBorderColorOpaqueBlack; + case VK_BORDER_COLOR_INT_OPAQUE_BLACK: return MTLSamplerBorderColorOpaqueBlack; + case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: return MTLSamplerBorderColorOpaqueWhite; + case VK_BORDER_COLOR_INT_OPAQUE_WHITE: return MTLSamplerBorderColorOpaqueWhite; + default: return MTLSamplerBorderColorTransparentBlack; + } +} +#endif + MVK_PUBLIC_SYMBOL MTLSamplerMinMagFilter mvkMTLSamplerMinMagFilterFromVkFilter(VkFilter vkFilter) { switch (vkFilter) { case VK_FILTER_NEAREST: return MTLSamplerMinMagFilterNearest;