Merge pull request #2042 from billhollings/VK_EXT_extended_dynamic_state-fixes

Fixes for VK_EXT_extended_dynamic_state.
This commit is contained in:
Bill Hollings 2023-10-16 22:25:05 -04:00 committed by GitHub
commit 107cf2c34e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 43 deletions

View File

@ -1711,7 +1711,11 @@ void MVKPhysicalDevice::initMetalFeatures() {
_metalFeatures.maxPerStageStorageTextureCount = 8;
_metalFeatures.vertexStrideAlignment = supportsMTLGPUFamily(Apple5) ? 1 : 4;
#if MVK_XCODE_15
// Dynamic vertex stride needs to have everything aligned - compiled with support for vertex stride calls, and supported by both runtime OS and GPU.
_metalFeatures.dynamicVertexStride = mvkOSVersionIsAtLeast(14.0, 17.0, 1.0) && (supportsMTLGPUFamily(Apple4) || supportsMTLGPUFamily(Mac2));
#endif
// GPU-specific features
switch (_properties.vendorID) {

View File

@ -232,6 +232,7 @@ enum MVKRenderStateType {
DepthTestEnable,
DepthWriteEnable,
FrontFace,
LineWidth,
LogicOp,
LogicOpEnable,
PatchControlPoints,

View File

@ -560,6 +560,7 @@ static MVKRenderStateType getRenderStateType(VkDynamicState vkDynamicState) {
case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE: return DepthTestEnable;
case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE: return DepthWriteEnable;
case VK_DYNAMIC_STATE_FRONT_FACE: return FrontFace;
case VK_DYNAMIC_STATE_LINE_WIDTH: return LineWidth;
case VK_DYNAMIC_STATE_LOGIC_OP_EXT: return LogicOp;
case VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT: return LogicOpEnable;
case VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT: return PatchControlPoints;
@ -1366,18 +1367,16 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
const VkVertexInputBindingDescription* pVKVB = &pVI->pVertexBindingDescriptions[i];
if (shaderConfig.isVertexBufferUsed(pVKVB->binding)) {
// Vulkan allows any stride, but Metal only allows multiples of 4.
// TODO: We could try to expand the buffer to the required alignment in that case.
VkDeviceSize mtlVtxStrideAlignment = _device->_pMetalFeatures->vertexStrideAlignment;
if ((pVKVB->stride % mtlVtxStrideAlignment) != 0) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex attribute binding strides must be aligned to %llu bytes.", mtlVtxStrideAlignment));
// Vulkan allows any stride, but Metal requires multiples of 4 on older GPUs.
if (isVtxStrideStatic && (pVKVB->stride % _device->_pMetalFeatures->vertexStrideAlignment) != 0) {
setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "Under Metal, vertex attribute binding strides must be aligned to %llu bytes.", _device->_pMetalFeatures->vertexStrideAlignment));
return false;
}
maxBinding = max(pVKVB->binding, maxBinding);
uint32_t vbIdx = getMetalBufferIndexForVertexAttributeBinding(pVKVB->binding);
auto vbDesc = inputDesc.layouts[vbIdx];
if (pVKVB->stride == 0) {
if (isVtxStrideStatic && pVKVB->stride == 0) {
// Stride can't be 0, it will be set later to attributes' maximum offset + size
// to prevent it from being larger than the underlying buffer permits.
vbDesc.stride = 0;
@ -1418,10 +1417,13 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
if (shaderConfig.isShaderInputLocationUsed(pVKVA->location)) {
uint32_t vaBinding = pVKVA->binding;
uint32_t vaOffset = pVKVA->offset;
auto vaDesc = inputDesc.attributes[pVKVA->location];
auto mtlFormat = (decltype(vaDesc.format))getPixelFormats()->getMTLVertexFormat(pVKVA->format);
// Vulkan allows offsets to exceed the buffer stride, but Metal doesn't.
// If this is the case, fetch a translated artificial buffer binding, using the same MTLBuffer,
// but that is translated so that the reduced VA offset fits into the binding stride.
if (isVtxStrideStatic) {
const VkVertexInputBindingDescription* pVKVB = pVI->pVertexBindingDescriptions;
uint32_t attrSize = 0;
for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) {
@ -1453,9 +1455,6 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
break;
}
}
auto vaDesc = inputDesc.attributes[pVKVA->location];
auto mtlFormat = (decltype(vaDesc.format))getPixelFormats()->getMTLVertexFormat(pVKVA->format);
if (pVKVB->stride && attrSize > pVKVB->stride) {
/* Metal does not support overlapping loads. Truncate format vector length to prevent an assertion
* and hope it's not used by the shader. */
@ -1464,6 +1463,8 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
attrSize, pVKVB->stride, getPixelFormats()->getName((MTLVertexFormat)mtlFormat), getPixelFormats()->getName(newFormat));
mtlFormat = (decltype(vaDesc.format))newFormat;
}
}
vaDesc.format = mtlFormat;
vaDesc.bufferIndex = (decltype(vaDesc.bufferIndex))getMetalBufferIndexForVertexAttributeBinding(vaBinding);
vaDesc.offset = vaOffset;