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 _mtlRasterizerDiscardEnable[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) {
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() {

View File

@ -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;

View File

@ -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)));

View File

@ -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;