Merge pull request 'perf(window): cache per-frame heap-bind structs across frames' (#77) from claude/issue-42 into master

This commit is contained in:
catbot 2026-06-16 17:27:55 +02:00
commit cea57f9af8
2 changed files with 41 additions and 21 deletions

View file

@ -768,27 +768,35 @@ void Window::Render() {
// Pass-side dispatches still run with the same heaps bound — moving
// the bind earlier doesn't change anything for them.
if (descriptorHeap) {
VkBindHeapInfoEXT resourceHeapInfo = {
.sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT,
.heapRange = {
.address = descriptorHeap->resourceHeap[currentBuffer].address,
.size = static_cast<std::uint32_t>(descriptorHeap->resourceHeap[currentBuffer].size)
},
.reservedRangeOffset = (descriptorHeap->resourceHeap[currentBuffer].size - Device::descriptorHeapProperties.minResourceHeapReservedRange) & ~(Device::descriptorHeapProperties.imageDescriptorAlignment - 1),
.reservedRangeSize = Device::descriptorHeapProperties.minResourceHeapReservedRange
};
Device::vkCmdBindResourceHeapEXT(drawCmdBuffers[currentBuffer], &resourceHeapInfo);
VkBindHeapInfoEXT samplerHeapInfo = {
.sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT,
.heapRange = {
.address = descriptorHeap->samplerHeap[currentBuffer].address,
.size = static_cast<std::uint32_t>(descriptorHeap->samplerHeap[currentBuffer].size)
},
.reservedRangeOffset = descriptorHeap->samplerHeap[currentBuffer].size - Device::descriptorHeapProperties.minSamplerHeapReservedRange,
.reservedRangeSize = Device::descriptorHeapProperties.minSamplerHeapReservedRange
};
Device::vkCmdBindSamplerHeapEXT(drawCmdBuffers[currentBuffer], &samplerHeapInfo);
// Rebuild the cached per-frame bind structs only when the heap changes.
// The address/size of each frame's heap and the reservedRangeOffset
// bitmask are stable for a given heap, so this runs once per assignment
// rather than every frame.
if (descriptorHeap != cachedDescriptorHeap) {
for (std::uint8_t i = 0; i < numFrames; ++i) {
resourceHeapInfos[i] = {
.sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT,
.heapRange = {
.address = descriptorHeap->resourceHeap[i].address,
.size = static_cast<std::uint32_t>(descriptorHeap->resourceHeap[i].size)
},
.reservedRangeOffset = (descriptorHeap->resourceHeap[i].size - Device::descriptorHeapProperties.minResourceHeapReservedRange) & ~(Device::descriptorHeapProperties.imageDescriptorAlignment - 1),
.reservedRangeSize = Device::descriptorHeapProperties.minResourceHeapReservedRange
};
samplerHeapInfos[i] = {
.sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT,
.heapRange = {
.address = descriptorHeap->samplerHeap[i].address,
.size = static_cast<std::uint32_t>(descriptorHeap->samplerHeap[i].size)
},
.reservedRangeOffset = descriptorHeap->samplerHeap[i].size - Device::descriptorHeapProperties.minSamplerHeapReservedRange,
.reservedRangeSize = Device::descriptorHeapProperties.minSamplerHeapReservedRange
};
}
cachedDescriptorHeap = descriptorHeap;
}
Device::vkCmdBindResourceHeapEXT(drawCmdBuffers[currentBuffer], &resourceHeapInfos[currentBuffer]);
Device::vkCmdBindSamplerHeapEXT(drawCmdBuffers[currentBuffer], &samplerHeapInfos[currentBuffer]);
}
onUpdate.Invoke({startTime, startTime-lastFrameBegin});