Handle vertex attributes with zero stride
This commit is contained in:
parent
6df700f6e7
commit
fa63b92d5d
@ -970,9 +970,17 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(MTLRenderPipelineDescriptor*
|
|||||||
maxBinding = max(pVKVB->binding, maxBinding);
|
maxBinding = max(pVKVB->binding, maxBinding);
|
||||||
uint32_t vbIdx = getMetalBufferIndexForVertexAttributeBinding(pVKVB->binding);
|
uint32_t vbIdx = getMetalBufferIndexForVertexAttributeBinding(pVKVB->binding);
|
||||||
MTLVertexBufferLayoutDescriptor* vbDesc = plDesc.vertexDescriptor.layouts[vbIdx];
|
MTLVertexBufferLayoutDescriptor* vbDesc = plDesc.vertexDescriptor.layouts[vbIdx];
|
||||||
vbDesc.stride = (pVKVB->stride == 0) ? sizeof(simd::float4) : pVKVB->stride; // Vulkan allows zero stride but Metal doesn't. Default to float4
|
if (pVKVB->stride == 0) {
|
||||||
vbDesc.stepFunction = mvkMTLVertexStepFunctionFromVkVertexInputRate(pVKVB->inputRate);
|
// Stride can't be 0, it will be set later to attributes' maximum offset + size
|
||||||
vbDesc.stepRate = 1;
|
// to prevent it from being larger than the underlying buffer permits.
|
||||||
|
vbDesc.stride = 0;
|
||||||
|
vbDesc.stepFunction = MTLVertexStepFunctionConstant;
|
||||||
|
vbDesc.stepRate = 0;
|
||||||
|
} else {
|
||||||
|
vbDesc.stride = pVKVB->stride;
|
||||||
|
vbDesc.stepFunction = mvkMTLVertexStepFunctionFromVkVertexInputRate(pVKVB->inputRate);
|
||||||
|
vbDesc.stepRate = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,26 +1012,31 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(MTLRenderPipelineDescriptor*
|
|||||||
// Vulkan allows offsets to exceed the buffer stride, but Metal doesn't.
|
// Vulkan allows offsets to exceed the buffer stride, but Metal doesn't.
|
||||||
// If this is the case, fetch an a translated artificial buffer binding, using the same MTLBuffer,
|
// If this is the case, fetch an a translated artificial buffer binding, using the same MTLBuffer,
|
||||||
// but that is translated so that the reduced VA offset fits into the binding stride.
|
// but that is translated so that the reduced VA offset fits into the binding stride.
|
||||||
// Only check non-zero offsets, as it's common for both to be zero when step rate is instance.
|
const VkVertexInputBindingDescription* pVKVB = pVI->pVertexBindingDescriptions;
|
||||||
if (vaOffset > 0) {
|
for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) {
|
||||||
const VkVertexInputBindingDescription* pVKVB = pVI->pVertexBindingDescriptions;
|
if (pVKVB->binding == pVKVA->binding) {
|
||||||
for (uint32_t j = 0; j < vbCnt; j++, pVKVB++) {
|
uint32_t attrSize = getPixelFormats()->getBytesPerBlock(pVKVA->format);
|
||||||
if (pVKVB->binding == pVKVA->binding) {
|
if (pVKVB->stride == 0) {
|
||||||
if (pVKVB->stride && vaOffset >= pVKVB->stride) {
|
// The step is set to constant, but we need to change stride to be non-zero for metal.
|
||||||
// Move vertex attribute offset into the stride. This vertex attribute may be
|
// Look for the maximum offset + size to set as the stride.
|
||||||
// combined with other vertex attributes into the same translated buffer binding.
|
uint32_t vbIdx = getMetalBufferIndexForVertexAttributeBinding(pVKVB->binding);
|
||||||
// But if the reduced offset combined with the vertex attribute size still won't
|
MTLVertexBufferLayoutDescriptor* vbDesc = plDesc.vertexDescriptor.layouts[vbIdx];
|
||||||
// fit into the buffer binding stride, force the vertex attribute offset to zero,
|
uint32_t strideLowBound = vaOffset + attrSize;
|
||||||
// effectively dedicating this vertex attribute to its own buffer binding.
|
if (vbDesc.stride < strideLowBound) vbDesc.stride = strideLowBound;
|
||||||
uint32_t origOffset = vaOffset;
|
} else if (vaOffset >= pVKVB->stride) {
|
||||||
vaOffset %= pVKVB->stride;
|
// Move vertex attribute offset into the stride. This vertex attribute may be
|
||||||
if (vaOffset + getPixelFormats()->getBytesPerBlock(pVKVA->format) > pVKVB->stride) {
|
// combined with other vertex attributes into the same translated buffer binding.
|
||||||
vaOffset = 0;
|
// But if the reduced offset combined with the vertex attribute size still won't
|
||||||
}
|
// fit into the buffer binding stride, force the vertex attribute offset to zero,
|
||||||
vaBinding = getTranslatedVertexBinding(vaBinding, origOffset - vaOffset, maxBinding);
|
// effectively dedicating this vertex attribute to its own buffer binding.
|
||||||
|
uint32_t origOffset = vaOffset;
|
||||||
|
vaOffset %= pVKVB->stride;
|
||||||
|
if (vaOffset + attrSize > pVKVB->stride) {
|
||||||
|
vaOffset = 0;
|
||||||
}
|
}
|
||||||
break;
|
vaBinding = getTranslatedVertexBinding(vaBinding, origOffset - vaOffset, maxBinding);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user