From d726aa043dfda5f3f1aee4a89fcb696335b664bf Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Tue, 22 Oct 2019 09:06:48 -0400 Subject: [PATCH 1/4] Set value of VkPhysicalDeviceLimits::maxTexelBufferElements to more realistic value. --- MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm | 8 ++++---- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm index b2d18e3f..15ba867a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm @@ -175,7 +175,7 @@ void MVKBufferView::propogateDebugName() { #pragma mark Metal id MVKBufferView::getMTLTexture() { - if ( !_mtlTexture && _mtlPixelFormat && _device->_pMetalFeatures->texelBuffers) { + if ( !_mtlTexture && _mtlPixelFormat && _device->_pMetalFeatures->texelBuffers) { // Lock and check again in case another thread has created the texture. lock_guard lock(_lock); @@ -201,9 +201,9 @@ id MVKBufferView::getMTLTexture() { mtlTexDesc.cpuCacheMode = mtlBuff.cpuCacheMode; mtlTexDesc.usage = usage; } - _mtlTexture = [_buffer->getMTLBuffer() newTextureWithDescriptor: mtlTexDesc - offset: _mtlBufferOffset - bytesPerRow: _mtlBytesPerRow]; + _mtlTexture = [mtlBuff newTextureWithDescriptor: mtlTexDesc + offset: _mtlBufferOffset + bytesPerRow: _mtlBytesPerRow]; propogateDebugName(); } return _mtlTexture; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index b116ae65..41a279e8 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -1197,11 +1197,9 @@ void MVKPhysicalDevice::initProperties() { _properties.limits.maxDescriptorSetStorageImages = (_properties.limits.maxPerStageDescriptorStorageImages * 4); _properties.limits.maxDescriptorSetInputAttachments = (_properties.limits.maxPerStageDescriptorInputAttachments * 4); - if (_metalFeatures.textureBuffers) { - _properties.limits.maxTexelBufferElements = (uint32_t)_metalFeatures.maxMTLBufferSize; - } else { - _properties.limits.maxTexelBufferElements = _properties.limits.maxImageDimension2D * _properties.limits.maxImageDimension2D; - } + // Whether handled as a real texture buffer or a 2D texture, this value is likely nowhere near the size of a buffer, + // needs to fit in 32 bits, and some apps (I'm looking at you, CTS), assume it is low when doing 32-bit math. + _properties.limits.maxTexelBufferElements = _properties.limits.maxImageDimension2D * (4 * KIBI); #if MVK_MACOS _properties.limits.maxUniformBufferRange = (64 * KIBI); #endif From 69cc9c97591653146b8228f3351e54b92cd77173 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Tue, 22 Oct 2019 11:17:30 -0400 Subject: [PATCH 2/4] ExternalDependencies Xcode project support Xcode 11. --- ExternalDependencies.xcodeproj/project.pbxproj | 2 +- .../xcschemes/ExternalDependencies (Debug).xcscheme | 2 +- .../xcshareddata/xcschemes/ExternalDependencies-iOS.xcscheme | 2 +- .../xcshareddata/xcschemes/ExternalDependencies-macOS.xcscheme | 2 +- .../xcshareddata/xcschemes/ExternalDependencies.xcscheme | 2 +- .../xcshareddata/xcschemes/SPIRV-Cross-iOS.xcscheme | 2 +- .../xcshareddata/xcschemes/SPIRV-Cross-macOS.xcscheme | 2 +- .../xcshareddata/xcschemes/SPIRV-Tools-iOS.xcscheme | 2 +- .../xcshareddata/xcschemes/SPIRV-Tools-macOS.xcscheme | 2 +- .../xcshareddata/xcschemes/glslang-iOS.xcscheme | 2 +- .../xcshareddata/xcschemes/glslang-macOS.xcscheme | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ExternalDependencies.xcodeproj/project.pbxproj b/ExternalDependencies.xcodeproj/project.pbxproj index 38d84094..9827d91b 100644 --- a/ExternalDependencies.xcodeproj/project.pbxproj +++ b/ExternalDependencies.xcodeproj/project.pbxproj @@ -2976,7 +2976,7 @@ A9F55D25198BE6A7004EC31B /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1100; + LastUpgradeCheck = 1110; ORGANIZATIONNAME = "The Brenwill Workshop Ltd."; TargetAttributes = { A972A7E421CEC72F0013AB25 = { diff --git a/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/ExternalDependencies (Debug).xcscheme b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/ExternalDependencies (Debug).xcscheme index 3d422f58..e283c6e0 100644 --- a/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/ExternalDependencies (Debug).xcscheme +++ b/ExternalDependencies.xcodeproj/xcshareddata/xcschemes/ExternalDependencies (Debug).xcscheme @@ -1,6 +1,6 @@ Date: Tue, 22 Oct 2019 16:51:27 -0400 Subject: [PATCH 3/4] Move generation of SPIRV-Cross/mvkSpirvCrossRevisionDerived.h to separate script. Add Scripts/gen_spirv_cross_rev_hdr.sh script and call from ExternalDependencies SPIRV-Cross build. --- .../project.pbxproj | 40 +++++++++++++++++++ Scripts/gen_spirv_cross_rev_hdr.sh | 11 +++++ fetchDependencies | 4 -- 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100755 Scripts/gen_spirv_cross_rev_hdr.sh diff --git a/ExternalDependencies.xcodeproj/project.pbxproj b/ExternalDependencies.xcodeproj/project.pbxproj index 9827d91b..e3b2b57f 100644 --- a/ExternalDependencies.xcodeproj/project.pbxproj +++ b/ExternalDependencies.xcodeproj/project.pbxproj @@ -1108,6 +1108,7 @@ 450A4F64221C5A95007203D7 /* spirv_reflect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spirv_reflect.cpp; sourceTree = ""; }; A90FD89F21CC4EAB00B92BB2 /* libSPIRVCross.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSPIRVCross.a; sourceTree = BUILT_PRODUCTS_DIR; }; A90FD9E421CC4EB900B92BB2 /* libSPIRVCross.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSPIRVCross.a; sourceTree = BUILT_PRODUCTS_DIR; }; + A91BF011235F9C510039B7DE /* gen_spirv_cross_rev_hdr.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = gen_spirv_cross_rev_hdr.sh; sourceTree = ""; }; A9679AAC21D269D900856BF7 /* package_ext_libs_macos.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = package_ext_libs_macos.sh; sourceTree = ""; }; A9679AAD21D269D900856BF7 /* package_ext_libs_ios.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = package_ext_libs_ios.sh; sourceTree = ""; }; A9679AAE21D269D900856BF7 /* package_ext_libs.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = package_ext_libs.sh; sourceTree = ""; }; @@ -1642,6 +1643,7 @@ A9679AAB21D2699800856BF7 /* Scripts */ = { isa = PBXGroup; children = ( + A91BF011235F9C510039B7DE /* gen_spirv_cross_rev_hdr.sh */, A9679AAD21D269D900856BF7 /* package_ext_libs_ios.sh */, A9679AAC21D269D900856BF7 /* package_ext_libs_macos.sh */, A9679AAE21D269D900856BF7 /* package_ext_libs.sh */, @@ -2880,6 +2882,7 @@ buildPhases = ( A976290021CC608E00B52A68 /* Headers */, A976290121CC609100B52A68 /* Sources */, + A91BF013235F9EED0039B7DE /* Generate Revision Header */, ); buildRules = ( ); @@ -2896,6 +2899,7 @@ buildPhases = ( A97628FF21CC608900B52A68 /* Headers */, A97628FE21CC608400B52A68 /* Sources */, + A91BF012235F9E220039B7DE /* Generate Revision Header */, ); buildRules = ( ); @@ -3018,6 +3022,42 @@ /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ + A91BF012235F9E220039B7DE /* Generate Revision Header */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Generate Revision Header"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Scripts/gen_spirv_cross_rev_hdr.sh\"\n"; + }; + A91BF013235F9EED0039B7DE /* Generate Revision Header */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Generate Revision Header"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Scripts/gen_spirv_cross_rev_hdr.sh\"\n"; + }; A9679AAF21D26C1400856BF7 /* Package External Libraries */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/Scripts/gen_spirv_cross_rev_hdr.sh b/Scripts/gen_spirv_cross_rev_hdr.sh new file mode 100755 index 00000000..d4311a60 --- /dev/null +++ b/Scripts/gen_spirv_cross_rev_hdr.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Record the SPIRV-Cross revision as a derived header file suitable for including in a build +EXT_DIR="${SRCROOT}/External" +EXT_REV_DIR="${SRCROOT}/ExternalRevisions" +REPO_NAME=SPIRV-Cross +REPO_REV=$(cat "${EXT_REV_DIR}/${REPO_NAME}_repo_revision") +HDR_FILE=${EXT_DIR}/${REPO_NAME}/mvkSpirvCrossRevisionDerived.h +echo "// Auto-generated by MoltenVK" > ${HDR_FILE} +echo "static const char* spirvCrossRevisionString = \"${REPO_REV}\";" >> ${HDR_FILE} + diff --git a/fetchDependencies b/fetchDependencies index 89ad70e3..08ce79ec 100755 --- a/fetchDependencies +++ b/fetchDependencies @@ -197,10 +197,6 @@ else update_repo ${REPO_NAME} ${REPO_URL} ${REPO_REV} fi -# Record the SPIRV-Cross revision as a derived header file suitable for including in a build -HDR_FILE=${REPO_NAME}/mvkSpirvCrossRevisionDerived.h -echo "// Auto-generated by MoltenVK" > ${HDR_FILE} -echo "static const char* spirvCrossRevisionString = \"${REPO_REV}\";" >> ${HDR_FILE} # ----------------- glslang ------------------- From 93ae214bc835ef00205628c77cbf5795acdcd8ae Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Fri, 25 Oct 2019 14:40:59 -0400 Subject: [PATCH 4/4] Support additional capabilities in 1D images, including rendering, clearing, and mipmaps. Add `MVK_CONFIG_TEXTURE_1D_AS_2D` environment variable, enabled by default. Modify 1D warning messages to recommend use of `MVK_CONFIG_TEXTURE_1D_AS_2D`. Update to latest version of SPIRV-Cross. Align pipeline cache contents to latest CompilerMSL::Options structure. Clean up code signing on demo Xcode projects. --- .../API-Samples.xcodeproj/project.pbxproj | 5 - .../Cube/Cube.xcodeproj/project.pbxproj | 5 - .../Hologram.xcodeproj/project.pbxproj | 5 - Docs/Whats_New.md | 3 + ExternalRevisions/SPIRV-Cross_repo_revision | 2 +- MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 10 +- MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm | 2 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 29 +++--- MoltenVK/MoltenVK/GPUObjects/MVKImage.h | 6 +- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 91 ++++++++++--------- MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 9 ++ MoltenVK/MoltenVK/Utility/MVKEnvironment.h | 5 + MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp | 3 + MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm | 26 ++++-- .../SPIRVToMSLConverter.cpp | 1 + 15 files changed, 118 insertions(+), 84 deletions(-) diff --git a/Demos/LunarG-VulkanSamples/API-Samples/API-Samples.xcodeproj/project.pbxproj b/Demos/LunarG-VulkanSamples/API-Samples/API-Samples.xcodeproj/project.pbxproj index 26b8d526..1fd91108 100644 --- a/Demos/LunarG-VulkanSamples/API-Samples/API-Samples.xcodeproj/project.pbxproj +++ b/Demos/LunarG-VulkanSamples/API-Samples/API-Samples.xcodeproj/project.pbxproj @@ -546,11 +546,6 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 1110; - TargetAttributes = { - A977BCBD1B66BB010067E5BF = { - DevelopmentTeam = VU3TCKU48B; - }; - }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "API-Samples" */; compatibilityVersion = "Xcode 8.0"; diff --git a/Demos/LunarG-VulkanSamples/Cube/Cube.xcodeproj/project.pbxproj b/Demos/LunarG-VulkanSamples/Cube/Cube.xcodeproj/project.pbxproj index 940a572f..f61eb24c 100644 --- a/Demos/LunarG-VulkanSamples/Cube/Cube.xcodeproj/project.pbxproj +++ b/Demos/LunarG-VulkanSamples/Cube/Cube.xcodeproj/project.pbxproj @@ -235,11 +235,6 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 1110; - TargetAttributes = { - A9B53B0F1C3AC0BE00ABC6F6 = { - DevelopmentTeam = VU3TCKU48B; - }; - }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Cube" */; compatibilityVersion = "Xcode 8.0"; diff --git a/Demos/LunarG-VulkanSamples/Hologram/Hologram.xcodeproj/project.pbxproj b/Demos/LunarG-VulkanSamples/Hologram/Hologram.xcodeproj/project.pbxproj index cefd96d0..90d5f3e4 100644 --- a/Demos/LunarG-VulkanSamples/Hologram/Hologram.xcodeproj/project.pbxproj +++ b/Demos/LunarG-VulkanSamples/Hologram/Hologram.xcodeproj/project.pbxproj @@ -266,11 +266,6 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 1110; - TargetAttributes = { - A977BCBD1B66BB010067E5BF = { - DevelopmentTeam = VU3TCKU48B; - }; - }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Hologram" */; compatibilityVersion = "Xcode 8.0"; diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index db86868f..b7dd8162 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -26,6 +26,9 @@ Released 2019/10/28 - Use native texture swizzling when available. - Set default value of the `MVK_ALLOW_METAL_FENCES` environment variable to `1 (true)`, to enable use of `MTLFence` for Vulkan semaphores, by default. +- Support additional capabilities in 1D images, including rendering, clearing, + and mipmaps. Add `MVK_CONFIG_TEXTURE_1D_AS_2D` environment variable to + enable/disable these capabilities. - Use placement `MTLHeaps` for `VkDeviceMemory` when possible. - Report heap sizes accurately when possible. - Add support for additional colorspace options. diff --git a/ExternalRevisions/SPIRV-Cross_repo_revision b/ExternalRevisions/SPIRV-Cross_repo_revision index 999ffa71..7ab941b6 100644 --- a/ExternalRevisions/SPIRV-Cross_repo_revision +++ b/ExternalRevisions/SPIRV-Cross_repo_revision @@ -1 +1 @@ -2082e7e80189843a52d9a79bc17787af93b517de +b10f5d48c959c5600c5e103a6b955b6b1b59cdff diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index 7a8d8cff..4af8c074 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -100,7 +100,7 @@ typedef unsigned long MTLLanguageVersion; * 0: No logging. * 1: Log errors only. * 2: Log errors and informational messages. - * If neither is set, errors and informational messages are logged. + * If none of these is set, errors and informational messages are logged. * * 2. The MVK_CONFIG_TRACE_VULKAN_CALLS runtime environment variable or MoltenVK compile-time build * setting causes MoltenVK to log the name of each Vulkan call made by the application. The logging @@ -114,6 +114,7 @@ typedef unsigned long MTLLanguageVersion; * * 3. Setting the MVK_CONFIG_FORCE_LOW_POWER_GPU runtime environment variable or MoltenVK compile-time * build setting to 1 will force MoltenVK to use a low-power GPU, if one is availble on the device. + * By default, this setting is disabled, allowing both low-power and high-power GPU's to be used. * * 4. Setting the MVK_ALLOW_METAL_FENCES or MVK_ALLOW_METAL_EVENTS runtime environment variable * or MoltenVK compile-time build setting to 1 will cause MoltenVK to use MTLFence or MTLEvent, @@ -136,6 +137,13 @@ typedef unsigned long MTLLanguageVersion; * 0: No automatic GPU capture. * 1: Capture all GPU commands issued during the lifetime of the VkDevice. * If none of these is set, no automatic GPU capture will occur. + * + * 6. The MVK_CONFIG_TEXTURE_1D_AS_2D runtime environment variable or MoltenVK compile-time build + * setting controls whether MoltenVK should use a Metal 2D texture with a height of 1 for a + * Vulkan 1D image, or use a native Metal 1D texture. Metal imposes significant restrictions + * on native 1D textures, including not being renderable, clearable, or permitting mipmaps. + * Using a Metal 2D texture allows Vulkan 1D textures to support this additional functionality. + * This setting is enabled by default, and MoltenVK will use a Metal 2D texture for each Vulkan 1D image. */ typedef struct { diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm index 71b5fb6c..435fd791 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm @@ -1061,7 +1061,7 @@ void MVKCmdClearImage::setContent(VkImage image, // Validate if (_image->getImageType() == VK_IMAGE_TYPE_1D) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdClearImage(): 1D images cannot be cleared on this device.")); + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdClearImage(): Native 1D images cannot be cleared on this device. Consider enabling MVK_CONFIG_TEXTURE_1D_AS_2D.")); } if ((_isDepthStencilClear && !_image->getSupportsAllFormatFeatures(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) || (!_isDepthStencilClear && !_image->getSupportsAllFormatFeatures(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))) { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 41a279e8..d68ceb17 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -264,21 +264,26 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, VkSampleCountFlags sampleCounts = _metalFeatures.supportedSampleCounts; switch (type) { case VK_IMAGE_TYPE_1D: - // Metal does not allow 1D textures to be used as attachments - if (hasAttachmentUsage) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } + maxExt.height = 1; + maxExt.depth = 1; + if (_mvkTexture1DAs2D) { + maxExt.width = pLimits->maxImageDimension2D; + maxLevels = mvkMipmapLevels3D(maxExt); + } else { + maxExt.width = pLimits->maxImageDimension1D; + maxLevels = 1; + sampleCounts = VK_SAMPLE_COUNT_1_BIT; - // Metal does not allow linear tiling on 1D textures - if (tiling == VK_IMAGE_TILING_LINEAR) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } + // Metal does not allow native 1D textures to be used as attachments + if (hasAttachmentUsage ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } - // Metal does not allow compressed or depth/stencil formats on 1D textures - if (mvkFmt == kMVKFormatDepthStencil || mvkFmt == kMVKFormatCompressed) { - return VK_ERROR_FORMAT_NOT_SUPPORTED; + // Metal does not allow linear tiling on native 1D textures + if (tiling == VK_IMAGE_TILING_LINEAR) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } + + // Metal does not allow compressed or depth/stencil formats on native 1D textures + if (mvkFmt == kMVKFormatDepthStencil) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } + if (mvkFmt == kMVKFormatCompressed) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } } - maxExt.width = pLimits->maxImageDimension1D; - maxExt.height = 1; - maxExt.depth = 1; - maxLevels = 1; - sampleCounts = VK_SAMPLE_COUNT_1_BIT; break; case VK_IMAGE_TYPE_2D: if (mvkIsAnyFlagEnabled(flags, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) ) { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index 2e25267b..4b37b307 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -56,7 +56,11 @@ public: /** Returns the debug report object type of this object. */ VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT; } - /** Returns the Vulkan image type of this image. */ + /** + * Returns the Vulkan image type of this image. + * This may be different than the value originally specified for the image + * if a 1D texture is being handled via a Metal 2D texture with height of 1. + */ VkImageType getImageType(); /** Returns the Vulkan image format of this image. */ diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index df00a3bd..8d0633ae 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -617,16 +617,18 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)); - validateConfig(pCreateInfo, isAttachment); + // Texture type depends on validated samples. Other validation depends on possibly modified texture type. _samples = validateSamples(pCreateInfo, isAttachment); + _mtlTextureType = mvkMTLTextureTypeFromVkImageType(pCreateInfo->imageType, _arrayLayers, _samples > VK_SAMPLE_COUNT_1_BIT); + + validateConfig(pCreateInfo, isAttachment); _mipLevels = validateMipLevels(pCreateInfo, isAttachment); _isLinear = validateLinear(pCreateInfo, isAttachment); _mtlPixelFormat = getMTLPixelFormatFromVkFormat(pCreateInfo->format); - _mtlTextureType = mvkMTLTextureTypeFromVkImageType(pCreateInfo->imageType, _arrayLayers, _samples > VK_SAMPLE_COUNT_1_BIT); _usage = pCreateInfo->usage; - _is3DCompressed = (pCreateInfo->imageType == VK_IMAGE_TYPE_3D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) && !getDevice()->_pMetalFeatures->native3DCompressedTextures; + _is3DCompressed = (getImageType() == VK_IMAGE_TYPE_3D) && (mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed) && !getDevice()->_pMetalFeatures->native3DCompressedTextures; _isDepthStencilAttachment = (mvkAreAllFlagsEnabled(pCreateInfo->usage, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) || mvkAreAllFlagsEnabled(mvkVkFormatProperties(pCreateInfo->format).optimalTilingFeatures, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)); _canSupportMTLTextureView = !_isDepthStencilAttachment || _device->_pMetalFeatures->stencilViews; @@ -650,50 +652,14 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV initSubresources(pCreateInfo); } -void MVKImage::validateConfig(const VkImageCreateInfo* pCreateInfo, bool isAttachment) { - - bool is2D = pCreateInfo->imageType == VK_IMAGE_TYPE_2D; - bool isCompressed = mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed; - -#if MVK_IOS - if (isCompressed && !is2D) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D images.")); - } -#endif -#if MVK_MACOS - if (isCompressed && !is2D) { - if (pCreateInfo->imageType != VK_IMAGE_TYPE_3D) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D or 3D images.")); - } else if (!getDevice()->_pMetalFeatures->native3DCompressedTextures && !mvkCanDecodeFormat(pCreateInfo->format)) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, the %s compressed format may only be used with 2D images.", mvkVkFormatName(pCreateInfo->format))); - } - } -#endif - - if ((mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatDepthStencil) && !is2D ) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, depth/stencil formats may only be used with 2D images.")); - } - if (isAttachment && (pCreateInfo->arrayLayers > 1) && !_device->_pMetalFeatures->layeredRendering) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : This device does not support rendering to array (layered) attachments.")); - } - if (isAttachment && (pCreateInfo->imageType == VK_IMAGE_TYPE_1D)) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : This device does not support rendering to 1D attachments.")); - } - if (mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not allow uncompressed views of compressed images.")); - } - if (mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT)) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not support split-instance memory binding.")); - } -} - VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment) { VkSampleCountFlagBits validSamples = pCreateInfo->samples; if (validSamples == VK_SAMPLE_COUNT_1_BIT) { return validSamples; } - if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) { + // Don't use getImageType() because it hasn't been set yet. + if ( !((pCreateInfo->imageType == VK_IMAGE_TYPE_2D) || ((pCreateInfo->imageType == VK_IMAGE_TYPE_1D) && _mvkTexture1DAs2D)) ) { setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, multisampling can only be used with a 2D image type. Setting sample count to 1.")); validSamples = VK_SAMPLE_COUNT_1_BIT; } @@ -717,14 +683,51 @@ VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreate return validSamples; } +void MVKImage::validateConfig(const VkImageCreateInfo* pCreateInfo, bool isAttachment) { + + bool is2D = (getImageType() == VK_IMAGE_TYPE_2D); + bool isCompressed = mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatCompressed; + +#if MVK_IOS + if (isCompressed && !is2D) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D images.")); + } +#endif +#if MVK_MACOS + if (isCompressed && !is2D) { + if (getImageType() != VK_IMAGE_TYPE_3D) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, compressed formats may only be used with 2D or 3D images.")); + } else if (!getDevice()->_pMetalFeatures->native3DCompressedTextures && !mvkCanDecodeFormat(pCreateInfo->format)) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, the %s compressed format may only be used with 2D images.", mvkVkFormatName(pCreateInfo->format))); + } + } +#endif + + if ((mvkFormatTypeFromVkFormat(pCreateInfo->format) == kMVKFormatDepthStencil) && !is2D ) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, depth/stencil formats may only be used with 2D images.")); + } + if (isAttachment && (pCreateInfo->arrayLayers > 1) && !_device->_pMetalFeatures->layeredRendering) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : This device does not support rendering to array (layered) attachments.")); + } + if (isAttachment && (getImageType() == VK_IMAGE_TYPE_1D)) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not support rendering to native 1D attachments. Consider enabling MVK_CONFIG_TEXTURE_1D_AS_2D.")); + } + if (mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not allow uncompressed views of compressed images.")); + } + if (mvkIsAnyFlagEnabled(pCreateInfo->flags, VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT)) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Metal does not support split-instance memory binding.")); + } +} + uint32_t MVKImage::validateMipLevels(const VkImageCreateInfo* pCreateInfo, bool isAttachment) { uint32_t minDim = 1; uint32_t validMipLevels = max(pCreateInfo->mipLevels, minDim); if (validMipLevels == 1) { return validMipLevels; } - if (pCreateInfo->imageType == VK_IMAGE_TYPE_1D) { - setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, 1D images cannot use mipmaps. Setting mip levels to 1.")); + if (getImageType() == VK_IMAGE_TYPE_1D) { + setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : Under Metal, native 1D images cannot use mipmaps. Setting mip levels to 1. Consider enabling MVK_CONFIG_TEXTURE_1D_AS_2D.")); validMipLevels = 1; } @@ -737,7 +740,7 @@ bool MVKImage::validateLinear(const VkImageCreateInfo* pCreateInfo, bool isAttac bool isLin = true; - if (pCreateInfo->imageType != VK_IMAGE_TYPE_2D) { + if (getImageType() != VK_IMAGE_TYPE_2D) { setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, imageType must be VK_IMAGE_TYPE_2D.")); isLin = false; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index cd0a2dc4..48a3f6ee 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -1157,6 +1157,7 @@ void MVKGraphicsPipeline::initMVKShaderConverterContext(SPIRVToMSLConversionConf _tessCtlPatchOutputBufferIndex = layout->getTessCtlPatchOutputBufferIndex(); _tessCtlLevelBufferIndex = layout->getTessCtlLevelBufferIndex(); + shaderContext.options.mslOptions.texture_1D_as_2D = _mvkTexture1DAs2D; shaderContext.options.mslOptions.enable_point_size_builtin = isRenderingPoints(pCreateInfo, reflectData); shaderContext.options.shouldFlipVertexY = _device->_pMVKConfig->shaderConversionFlipVertexY; shaderContext.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle; @@ -1349,6 +1350,7 @@ MVKMTLFunction MVKComputePipeline::getMTLFunction(const VkComputePipelineCreateI shaderContext.options.mslOptions.swizzle_texture_samples = _fullImageViewSwizzle && !getDevice()->_pMetalFeatures->nativeTextureSwizzle; shaderContext.options.mslOptions.texture_buffer_native = _device->_pMetalFeatures->textureBuffers; shaderContext.options.mslOptions.dispatch_base = _allowsDispatchBase; + shaderContext.options.mslOptions.texture_1D_as_2D = _mvkTexture1DAs2D; MVKPipelineLayout* layout = (MVKPipelineLayout*)pCreateInfo->layout; layout->populateShaderConverterContext(shaderContext); @@ -1615,12 +1617,19 @@ namespace SPIRV_CROSS_NAMESPACE { opt.shader_patch_output_buffer_index, opt.shader_tess_factor_buffer_index, opt.buffer_size_buffer_index, + opt.view_mask_buffer_index, + opt.dynamic_offsets_buffer_index, opt.shader_input_wg_index, + opt.device_index, opt.enable_point_size_builtin, opt.disable_rasterization, opt.capture_output_to_buffer, opt.swizzle_texture_samples, opt.tess_domain_origin_lower_left, + opt.multiview, + opt.view_index_from_device_index, + opt.dispatch_base, + opt.texture_1D_as_2D, opt.argument_buffers, opt.pad_fragment_output_components, opt.texture_buffer_native); diff --git a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h index ae1c4bda..2f40b2f3 100644 --- a/MoltenVK/MoltenVK/Utility/MVKEnvironment.h +++ b/MoltenVK/MoltenVK/Utility/MVKEnvironment.h @@ -184,6 +184,11 @@ # define MVK_ALLOW_METAL_EVENTS 0 #endif +/** Substitute Metal 2D textures for Vulkan 1D images. Enabled by default. */ +#ifndef MVK_CONFIG_TEXTURE_1D_AS_2D +# define MVK_CONFIG_TEXTURE_1D_AS_2D 1 +#endif + /** * IOSurfaces are supported on macOS, and on iOS starting with iOS 11. * diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp index 617db53f..66c880d5 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.hpp @@ -31,6 +31,9 @@ class MVKBaseObject; * which is part of the public external MoltenVK C API. */ +/** Support the MVK_CONFIG_TEXTURE_1D_AS_2D runtime environment variable. */ +extern bool _mvkTexture1DAs2D; + #pragma mark - #pragma mark Support for VK_EXT_debug_report extension diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm index a24700fb..c0a631f5 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm @@ -821,8 +821,10 @@ MVK_PUBLIC_SYMBOL MTLTextureType mvkMTLTextureTypeFromVkImageType(VkImageType vk uint32_t arraySize, bool isMultisample) { switch (vkImageType) { - case VK_IMAGE_TYPE_1D: return (arraySize > 1 ? MTLTextureType1DArray : MTLTextureType1D); case VK_IMAGE_TYPE_3D: return MTLTextureType3D; + case VK_IMAGE_TYPE_1D: return (_mvkTexture1DAs2D + ? mvkMTLTextureTypeFromVkImageType(VK_IMAGE_TYPE_2D, arraySize, isMultisample) + : (arraySize > 1 ? MTLTextureType1DArray : MTLTextureType1D)); case VK_IMAGE_TYPE_2D: default: { #if MVK_MACOS @@ -846,22 +848,24 @@ MVK_PUBLIC_SYMBOL VkImageType mvkVkImageTypeFromMTLTextureType(MTLTextureType mt return VK_IMAGE_TYPE_2D; } } - MVK_PUBLIC_SYMBOL MTLTextureType mvkMTLTextureTypeFromVkImageViewType(VkImageViewType vkImageViewType, bool isMultisample) { switch (vkImageViewType) { - case VK_IMAGE_VIEW_TYPE_1D: return MTLTextureType1D; - case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return MTLTextureType1DArray; - case VK_IMAGE_VIEW_TYPE_2D: return (isMultisample ? MTLTextureType2DMultisample : MTLTextureType2D); + case VK_IMAGE_VIEW_TYPE_3D: return MTLTextureType3D; + case VK_IMAGE_VIEW_TYPE_CUBE: return MTLTextureTypeCube; + case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return MTLTextureTypeCubeArray; + case VK_IMAGE_VIEW_TYPE_1D: return _mvkTexture1DAs2D ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D, isMultisample) : MTLTextureType1D; + case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return _mvkTexture1DAs2D ? mvkMTLTextureTypeFromVkImageViewType(VK_IMAGE_VIEW_TYPE_2D_ARRAY, isMultisample) : MTLTextureType1DArray; + case VK_IMAGE_VIEW_TYPE_2D_ARRAY: #if MVK_MACOS if (isMultisample) { return MTLTextureType2DMultisampleArray; } #endif return MTLTextureType2DArray; - case VK_IMAGE_VIEW_TYPE_3D: return MTLTextureType3D; - case VK_IMAGE_VIEW_TYPE_CUBE: return MTLTextureTypeCube; - case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return MTLTextureTypeCubeArray; - default: return MTLTextureType2D; + + case VK_IMAGE_VIEW_TYPE_2D: + default: + return (isMultisample ? MTLTextureType2DMultisample : MTLTextureType2D); } } @@ -1450,6 +1454,8 @@ MVK_PUBLIC_SYMBOL MTLResourceOptions mvkMTLResourceOptions(MTLStorageMode mtlSto #pragma mark - #pragma mark Library initialization +bool _mvkTexture1DAs2D = MVK_CONFIG_TEXTURE_1D_AS_2D; + /** * Called automatically when the framework is loaded and initialized. * @@ -1461,6 +1467,8 @@ __attribute__((constructor)) static void MVKInitDataTypes() { MVKInitFormatMaps(); + MVK_SET_FROM_ENV_OR_BUILD_BOOL(_mvkTexture1DAs2D, MVK_CONFIG_TEXTURE_1D_AS_2D); + _mvkDataTypesInitialized = true; } diff --git a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp index 59790c32..126c93a9 100644 --- a/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp +++ b/MoltenVKShaderConverter/MoltenVKSPIRVToMSLConverter/SPIRVToMSLConverter.cpp @@ -63,6 +63,7 @@ MVK_PUBLIC_SYMBOL bool SPIRVToMSLConversionOptions::matches(const SPIRVToMSLConv if (mslOptions.argument_buffers != other.mslOptions.argument_buffers) { return false; } if (mslOptions.pad_fragment_output_components != other.mslOptions.pad_fragment_output_components) { return false; } if (mslOptions.texture_buffer_native != other.mslOptions.texture_buffer_native) { return false; } + if (mslOptions.texture_1D_as_2D != other.mslOptions.texture_1D_as_2D) { return false; } return true; }