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).
This commit is contained in:
Bill Hollings 2023-12-17 16:57:32 -05:00
parent 2cccfd516e
commit c4b7232f36
5 changed files with 37 additions and 12 deletions

View File

@ -332,6 +332,7 @@ protected:
bool _mtlPrimitiveRestartEnable[StateScope::Count] = {}; bool _mtlPrimitiveRestartEnable[StateScope::Count] = {};
bool _mtlRasterizerDiscardEnable[StateScope::Count] = {}; bool _mtlRasterizerDiscardEnable[StateScope::Count] = {};
bool _cullBothFaces[StateScope::Count] = {}; bool _cullBothFaces[StateScope::Count] = {};
bool _isPolygonModePoint[StateScope::Count] = {};
}; };

View File

@ -302,7 +302,7 @@ void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) {
void MVKRenderingCommandEncoderState::setCullMode(VkCullModeFlags cullMode, bool isDynamic) { void MVKRenderingCommandEncoderState::setCullMode(VkCullModeFlags cullMode, bool isDynamic) {
auto mtlCullMode = mvkMTLCullModeFromVkCullModeFlags(cullMode); auto mtlCullMode = mvkMTLCullModeFromVkCullModeFlags(cullMode);
setMTLContent(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) { 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) { void MVKRenderingCommandEncoderState::setPolygonMode(VkPolygonMode polygonMode, bool isDynamic) {
auto mtlPolygonMode = mvkMTLTriangleFillModeFromVkPolygonMode(polygonMode); auto mtlPolygonMode = mvkMTLTriangleFillModeFromVkPolygonMode(polygonMode);
setMTLContent(PolygonMode); setMTLContent(PolygonMode);
getContent(_isPolygonModePoint, isDynamic) = (polygonMode == VK_POLYGON_MODE_POINT);
} }
void MVKRenderingCommandEncoderState::setBlendConstants(float blendConstants[4], bool isDynamic) { void MVKRenderingCommandEncoderState::setBlendConstants(float blendConstants[4], bool isDynamic) {
@ -420,8 +421,20 @@ void MVKRenderingCommandEncoderState::setPrimitiveTopology(VkPrimitiveTopology t
getContent(_mtlPrimitiveTopology, isDynamic) = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(topology); 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() { 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() { bool MVKRenderingCommandEncoderState::isDrawingTriangles() {

View File

@ -762,6 +762,11 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
portabilityProps->minVertexInputBindingStrideAlignment = (uint32_t)_metalFeatures.vertexStrideAlignment; portabilityProps->minVertexInputBindingStrideAlignment = (uint32_t)_metalFeatures.vertexStrideAlignment;
break; 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: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: {
auto* extMemHostProps = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT*)next; auto* extMemHostProps = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT*)next;
extMemHostProps->minImportedHostPointerAlignment = _metalFeatures.hostMemoryPageSize; extMemHostProps->minImportedHostPointerAlignment = _metalFeatures.hostMemoryPageSize;

View File

@ -511,11 +511,12 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
} }
// Topology // Topology
_vkPrimitiveTopology = (pCreateInfo->pInputAssemblyState && !isRenderingPoints(pCreateInfo) _vkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
? pCreateInfo->pInputAssemblyState->topology _primitiveRestartEnable = true; // Always enabled in Metal
: VK_PRIMITIVE_TOPOLOGY_POINT_LIST); if (pCreateInfo->pInputAssemblyState) {
_vkPrimitiveTopology = pCreateInfo->pInputAssemblyState->topology;
_primitiveRestartEnable = pCreateInfo->pInputAssemblyState ? pCreateInfo->pInputAssemblyState->primitiveRestartEnable : true; _primitiveRestartEnable = pCreateInfo->pInputAssemblyState->primitiveRestartEnable;
}
// Rasterization // Rasterization
_hasRasterInfo = mvkSetOrClear(&_rasterInfo, pCreateInfo->pRasterizationState); _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) { bool MVKGraphicsPipeline::isRenderingPoints(const VkGraphicsPipelineCreateInfo* pCreateInfo) {
return ((pCreateInfo->pInputAssemblyState && return ((pCreateInfo->pInputAssemblyState &&
(pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) && (pCreateInfo->pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)) ||
!isDynamicState(PrimitiveTopology)) ||
(pCreateInfo->pRasterizationState && (pCreateInfo->pRasterizationState &&
(pCreateInfo->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT) && (pCreateInfo->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT) &&
!isDynamicState(PolygonMode))); !isDynamicState(PolygonMode)));

View File

@ -509,8 +509,8 @@ MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonModeInObj(VkPolygonMode v
case VK_POLYGON_MODE_FILL: case VK_POLYGON_MODE_FILL:
return MTLTriangleFillModeFill; return MTLTriangleFillModeFill;
// Metal does not support VK_POLYGON_MODE_POINT. Next best option is lines.
case VK_POLYGON_MODE_POINT: 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: case VK_POLYGON_MODE_LINE:
return MTLTriangleFillModeLines; return MTLTriangleFillModeLines;