Track if indirect tessellation drawing is supported.

Add MVKPhysicalDeviceMetalFeatures::indirectTessellationDrawing.
Return error if indirect tessellated draw command is used when not supported.
This commit is contained in:
Bill Hollings 2020-07-21 14:10:20 -04:00
parent 9b1ec34ce7
commit 81ec314787
4 changed files with 63 additions and 51 deletions

View File

@ -34,6 +34,7 @@ Released TBD
- Fix new and unexpected App Store failure on newly deprecated color space values.
- Include vertex attribute size when testing whether attribute offset exceeds stride.
- Add `MVKPhysicalDeviceMetalFeatures::vertexStrideAlignment` to track Metal vertex binding stride alignment.
- Add `MVKPhysicalDeviceMetalFeatures::indirectTessellationDrawing` to track if indirect tessellation drawing is supported.
- Remove use of `@available()` directive as it was causing issues in some build environments.
- Refactor **MoltenVK** *Xcode* build architectures.
- Demo `API-Samples generateSPIRVShaders` no longer builds `MoltenVKShaderController` tool.

View File

@ -613,6 +613,7 @@ typedef struct {
uint32_t maxTextureLayers; /**< The maximum number of layers in an array texture. */
uint32_t subgroupSize; /**< The number of threads in a SIMD-group. */
VkDeviceSize vertexStrideAlignment; /**< The alignment used for the stride of vertex attribute bindings. */
VkBool32 indirectTessellationDrawing; /**< If true, tessellation draw calls support parameters held in a GPU buffer. */
} MVKPhysicalDeviceMetalFeatures;
/** MoltenVK performance of a particular type of activity. */

View File

@ -520,9 +520,13 @@ VkResult MVKCmdDrawIndirect::setContent(MVKCommandBuffer* cmdBuff,
_storeOverride = false;
// Validate
if ( !(cmdBuff->getDevice()->_pMetalFeatures->indirectDrawing) ) {
MVKDevice* mvkDvc = cmdBuff->getDevice();
if ( !mvkDvc->_pMetalFeatures->indirectDrawing ) {
return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndirect(): The current device does not support indirect drawing.");
}
if (cmdBuff->_lastTessellationPipeline && !mvkDvc->_pMetalFeatures->indirectTessellationDrawing) {
return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndirect(): The current device does not support indirect tessellated drawing.");
}
cmdBuff->recordDraw(this);
return VK_SUCCESS;
@ -707,32 +711,32 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
break;
case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) {
if (pipeline->needsTessCtlOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcOutBuff->_mtlBuffer
offset: tcOutBuff->_offset
atIndex: kMVKTessEvalInputBufferIndex];
}
if (pipeline->needsTessCtlPatchOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcPatchOutBuff->_mtlBuffer
offset: tcPatchOutBuff->_offset
atIndex: kMVKTessEvalPatchInputBufferIndex];
}
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
atIndex: kMVKTessEvalLevelBufferIndex];
[cmdEncoder->_mtlRenderEncoder setTessellationFactorBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
instanceStride: 0];
if (cmdEncoder->getDevice()->_pMetalFeatures->indirectTessellationDrawing) {
if (pipeline->needsTessCtlOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcOutBuff->_mtlBuffer
offset: tcOutBuff->_offset
atIndex: kMVKTessEvalInputBufferIndex];
}
if (pipeline->needsTessCtlPatchOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcPatchOutBuff->_mtlBuffer
offset: tcPatchOutBuff->_offset
atIndex: kMVKTessEvalPatchInputBufferIndex];
}
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
atIndex: kMVKTessEvalLevelBufferIndex];
[cmdEncoder->_mtlRenderEncoder setTessellationFactorBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
instanceStride: 0];
#if MVK_MACOS_OR_IOS
[cmdEncoder->_mtlRenderEncoder drawPatches: outControlPointCount
patchIndexBuffer: nil
patchIndexBufferOffset: 0
indirectBuffer: tcIndirectBuff->_mtlBuffer
indirectBufferOffset: mtlTCIndBuffOfst];
#endif
#if MVK_TVOS
cmdEncoder->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect tessellated drawing.");
[cmdEncoder->_mtlRenderEncoder drawPatches: outControlPointCount
patchIndexBuffer: nil
patchIndexBufferOffset: 0
indirectBuffer: tcIndirectBuff->_mtlBuffer
indirectBufferOffset: mtlTCIndBuffOfst];
#endif
}
mtlTCIndBuffOfst += sizeof(MTLDrawPatchIndirectArguments);
// Mark pipeline, resources, and tess control push constants as dirty
// so I apply them during the next stage.
@ -769,9 +773,13 @@ VkResult MVKCmdDrawIndexedIndirect::setContent(MVKCommandBuffer* cmdBuff,
_storeOverride = false;
// Validate
if ( !(cmdBuff->getDevice()->_pMetalFeatures->indirectDrawing) ) {
MVKDevice* mvkDvc = cmdBuff->getDevice();
if ( !mvkDvc->_pMetalFeatures->indirectDrawing ) {
return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect drawing.");
}
if (cmdBuff->_lastTessellationPipeline && !mvkDvc->_pMetalFeatures->indirectTessellationDrawing) {
return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect tessellated drawing.");
}
cmdBuff->recordDraw(this);
return VK_SUCCESS;
@ -967,32 +975,32 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) {
break;
case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) {
if (pipeline->needsTessCtlOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcOutBuff->_mtlBuffer
offset: tcOutBuff->_offset
atIndex: kMVKTessEvalInputBufferIndex];
}
if (pipeline->needsTessCtlPatchOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcPatchOutBuff->_mtlBuffer
offset: tcPatchOutBuff->_offset
atIndex: kMVKTessEvalPatchInputBufferIndex];
}
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
atIndex: kMVKTessEvalLevelBufferIndex];
[cmdEncoder->_mtlRenderEncoder setTessellationFactorBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
instanceStride: 0];
if (cmdEncoder->getDevice()->_pMetalFeatures->indirectTessellationDrawing) {
if (pipeline->needsTessCtlOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcOutBuff->_mtlBuffer
offset: tcOutBuff->_offset
atIndex: kMVKTessEvalInputBufferIndex];
}
if (pipeline->needsTessCtlPatchOutputBuffer()) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcPatchOutBuff->_mtlBuffer
offset: tcPatchOutBuff->_offset
atIndex: kMVKTessEvalPatchInputBufferIndex];
}
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
atIndex: kMVKTessEvalLevelBufferIndex];
[cmdEncoder->_mtlRenderEncoder setTessellationFactorBuffer: tcLevelBuff->_mtlBuffer
offset: tcLevelBuff->_offset
instanceStride: 0];
#if MVK_MACOS_OR_IOS
[cmdEncoder->_mtlRenderEncoder drawPatches: outControlPointCount
patchIndexBuffer: nil
patchIndexBufferOffset: 0
indirectBuffer: tcIndirectBuff->_mtlBuffer
indirectBufferOffset: mtlTCIndBuffOfst];
#endif
#if MVK_TVOS
cmdEncoder->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdDrawIndexedIndirect(): The current device does not support indirect tessellated drawing.");
[cmdEncoder->_mtlRenderEncoder drawPatches: outControlPointCount
patchIndexBuffer: nil
patchIndexBufferOffset: 0
indirectBuffer: tcIndirectBuff->_mtlBuffer
indirectBufferOffset: mtlTCIndBuffOfst];
#endif
}
mtlTCIndBuffOfst += sizeof(MTLDrawPatchIndirectArguments);
// Mark pipeline, resources, and tess control push constants as dirty
// so I apply them during the next stage.

View File

@ -1063,6 +1063,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
if (supportsMTLFeatureSet(iOS_GPUFamily5_v1)) {
_metalFeatures.layeredRendering = true;
_metalFeatures.stencilFeedback = true;
_metalFeatures.indirectTessellationDrawing = true;
}
if ( mvkOSVersionIsAtLeast(13.0) ) {
@ -1080,7 +1081,6 @@ void MVKPhysicalDevice::initMetalFeatures() {
_metalFeatures.maxPerStageTextureCount = 128;
_metalFeatures.mtlBufferAlignment = 256;
_metalFeatures.mtlCopyBufferAlignment = 4;
_metalFeatures.indirectDrawing = true;
_metalFeatures.baseVertexInstanceDrawing = true;
_metalFeatures.layeredRendering = true;
_metalFeatures.maxTextureDimension = (16 * KIBI);
@ -1088,6 +1088,8 @@ void MVKPhysicalDevice::initMetalFeatures() {
if (supportsMTLFeatureSet(macOS_GPUFamily1_v2)) {
_metalFeatures.mslVersionEnum = MTLLanguageVersion1_2;
_metalFeatures.indirectDrawing = true;
_metalFeatures.indirectTessellationDrawing = true;
_metalFeatures.dynamicMTLBufferSize = (4 * KIBI);
_metalFeatures.shaderSpecialization = true;
_metalFeatures.stencilViews = true;