From c4b7232f3647787f8c333743483e9636e575b1ef Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Sun, 17 Dec 2023 16:57:32 -0500 Subject: [PATCH] Fix regression error and properties in point-topology/polygon-mode behavior. - MVKGraphicsPipeline::isRenderingPoints() fix regression error to support dynamically setting point topology. - Move emulation of VK_POLYGON_MODE_POINT in Metal, if the polygon model is static, to MVKRenderingCommandEncoderState, to handle dynamic setting of topology. - MVKDevice populate VkPhysicalDeviceExtendedDynamicState3PropertiesEXT. - Move error reporting in mvkMTLTriangleFillModeFromVkPolygonModeInObj() to encoding. - MVKRenderingCommandEncoderState::setCullMode() use getContent() for readability and consistency (unrelated). - Pass pipeline object to datatype functions for reporting accuracy (unrelated). --- .../Commands/MVKCommandEncoderState.h | 1 + .../Commands/MVKCommandEncoderState.mm | 17 +++++++++++-- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 5 ++++ MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm | 24 ++++++++++++------- MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm | 2 +- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h index 4ac895d4..865cd1c0 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h @@ -332,6 +332,7 @@ protected: bool _mtlPrimitiveRestartEnable[StateScope::Count] = {}; bool _mtlRasterizerDiscardEnable[StateScope::Count] = {}; bool _cullBothFaces[StateScope::Count] = {}; + bool _isPolygonModePoint[StateScope::Count] = {}; }; diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm index c7246a51..769230bc 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.mm @@ -302,7 +302,7 @@ void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) { void MVKRenderingCommandEncoderState::setCullMode(VkCullModeFlags cullMode, bool isDynamic) { auto mtlCullMode = mvkMTLCullModeFromVkCullModeFlags(cullMode); setMTLContent(CullMode); - _cullBothFaces[isDynamic ? StateScope::Dynamic : StateScope::Static] = (cullMode == VK_CULL_MODE_FRONT_AND_BACK); + getContent(_cullBothFaces, isDynamic) = (cullMode == VK_CULL_MODE_FRONT_AND_BACK); } void MVKRenderingCommandEncoderState::setFrontFace(VkFrontFace frontFace, bool isDynamic) { @@ -313,6 +313,7 @@ void MVKRenderingCommandEncoderState::setFrontFace(VkFrontFace frontFace, bool i void MVKRenderingCommandEncoderState::setPolygonMode(VkPolygonMode polygonMode, bool isDynamic) { auto mtlPolygonMode = mvkMTLTriangleFillModeFromVkPolygonMode(polygonMode); setMTLContent(PolygonMode); + getContent(_isPolygonModePoint, isDynamic) = (polygonMode == VK_POLYGON_MODE_POINT); } void MVKRenderingCommandEncoderState::setBlendConstants(float blendConstants[4], bool isDynamic) { @@ -420,8 +421,20 @@ void MVKRenderingCommandEncoderState::setPrimitiveTopology(VkPrimitiveTopology t getContent(_mtlPrimitiveTopology, isDynamic) = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(topology); } +// Metal does not support VK_POLYGON_MODE_POINT, but it can be emulated if the polygon mode +// is static, which allows both the topology and the pipeline topology-class to be set to points. +// This cannot be accomplished if the dynamic polygon mode has been changed to points when the +// pipeline is expecting triangles or lines, because the pipeline topology class will be incorrect. MTLPrimitiveType MVKRenderingCommandEncoderState::getPrimitiveType() { - return getMTLContent(PrimitiveTopology); + if (isDynamicState(PolygonMode) && + _isPolygonModePoint[StateScope::Dynamic] && + !_isPolygonModePoint[StateScope::Static]) { + + reportWarning(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetPolygonMode(): Metal does not support setting VK_POLYGON_MODE_POINT dynamically."); + return getMTLContent(PrimitiveTopology); + } + + return getContent(_isPolygonModePoint, PolygonMode) ? MTLPrimitiveTypePoint : getMTLContent(PrimitiveTopology); } bool MVKRenderingCommandEncoderState::isDrawingTriangles() { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index af016e51..5dd3c976 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -762,6 +762,11 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { portabilityProps->minVertexInputBindingStrideAlignment = (uint32_t)_metalFeatures.vertexStrideAlignment; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT: { + auto* extDynState3Props = (VkPhysicalDeviceExtendedDynamicState3PropertiesEXT*)next; + extDynState3Props->dynamicPrimitiveTopologyUnrestricted = false; + break; + } case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: { auto* extMemHostProps = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT*)next; extMemHostProps->minImportedHostPointerAlignment = _metalFeatures.hostMemoryPageSize; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index c85ef684..3b5dd95d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -511,11 +511,12 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device, } // Topology - _vkPrimitiveTopology = (pCreateInfo->pInputAssemblyState && !isRenderingPoints(pCreateInfo) - ? pCreateInfo->pInputAssemblyState->topology - : VK_PRIMITIVE_TOPOLOGY_POINT_LIST); - - _primitiveRestartEnable = pCreateInfo->pInputAssemblyState ? pCreateInfo->pInputAssemblyState->primitiveRestartEnable : true; + _vkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST; + _primitiveRestartEnable = true; // Always enabled in Metal + if (pCreateInfo->pInputAssemblyState) { + _vkPrimitiveTopology = pCreateInfo->pInputAssemblyState->topology; + _primitiveRestartEnable = pCreateInfo->pInputAssemblyState->primitiveRestartEnable; + } // Rasterization _hasRasterInfo = mvkSetOrClear(&_rasterInfo, pCreateInfo->pRasterizationState); @@ -1933,11 +1934,16 @@ void MVKGraphicsPipeline::addPrevStageOutputToShaderConversionConfig(SPIRVToMSLC } } -// We render points if either the static topology or static polygon fill mode dictate it +// We render points if either the static topology or static polygon-mode dictate it. +// The topology class must be the same between static and dynamic, so point topology +// in static also implies point topology in dynamic. +// Metal does not support VK_POLYGON_MODE_POINT, but it can be emulated if the polygon mode +// is static, which allows both the topology and the pipeline topology-class to be set to points. +// This cannot be accomplished if the dynamic polygon mode has been changed to points when the +// pipeline is expecting triangles or lines, because the pipeline topology class will be incorrect. bool MVKGraphicsPipeline::isRenderingPoints(const VkGraphicsPipelineCreateInfo* pCreateInfo) { - return ((pCreateInfo->pInputAssemblyState && - (pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) && - !isDynamicState(PrimitiveTopology)) || + return ((pCreateInfo->pInputAssemblyState && + (pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)) || (pCreateInfo->pRasterizationState && (pCreateInfo->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT) && !isDynamicState(PolygonMode))); diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm index 8fdbc1a6..27b87df1 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm @@ -509,8 +509,8 @@ MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonModeInObj(VkPolygonMode v case VK_POLYGON_MODE_FILL: return MTLTriangleFillModeFill; + // Metal does not support VK_POLYGON_MODE_POINT. Next best option is lines. case VK_POLYGON_MODE_POINT: - MVKBaseObject::reportError(mvkObj, VK_ERROR_FORMAT_NOT_SUPPORTED, "VkPolygonMode value VK_POLYGON_MODE_POINT is not supported for render pipelines."); case VK_POLYGON_MODE_LINE: return MTLTriangleFillModeLines;