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:
commit
cea57f9af8
2 changed files with 41 additions and 21 deletions
|
|
@ -768,27 +768,35 @@ void Window::Render() {
|
||||||
// Pass-side dispatches still run with the same heaps bound — moving
|
// Pass-side dispatches still run with the same heaps bound — moving
|
||||||
// the bind earlier doesn't change anything for them.
|
// the bind earlier doesn't change anything for them.
|
||||||
if (descriptorHeap) {
|
if (descriptorHeap) {
|
||||||
VkBindHeapInfoEXT resourceHeapInfo = {
|
// 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,
|
.sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT,
|
||||||
.heapRange = {
|
.heapRange = {
|
||||||
.address = descriptorHeap->resourceHeap[currentBuffer].address,
|
.address = descriptorHeap->resourceHeap[i].address,
|
||||||
.size = static_cast<std::uint32_t>(descriptorHeap->resourceHeap[currentBuffer].size)
|
.size = static_cast<std::uint32_t>(descriptorHeap->resourceHeap[i].size)
|
||||||
},
|
},
|
||||||
.reservedRangeOffset = (descriptorHeap->resourceHeap[currentBuffer].size - Device::descriptorHeapProperties.minResourceHeapReservedRange) & ~(Device::descriptorHeapProperties.imageDescriptorAlignment - 1),
|
.reservedRangeOffset = (descriptorHeap->resourceHeap[i].size - Device::descriptorHeapProperties.minResourceHeapReservedRange) & ~(Device::descriptorHeapProperties.imageDescriptorAlignment - 1),
|
||||||
.reservedRangeSize = Device::descriptorHeapProperties.minResourceHeapReservedRange
|
.reservedRangeSize = Device::descriptorHeapProperties.minResourceHeapReservedRange
|
||||||
};
|
};
|
||||||
Device::vkCmdBindResourceHeapEXT(drawCmdBuffers[currentBuffer], &resourceHeapInfo);
|
samplerHeapInfos[i] = {
|
||||||
|
|
||||||
VkBindHeapInfoEXT samplerHeapInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT,
|
.sType = VK_STRUCTURE_TYPE_BIND_HEAP_INFO_EXT,
|
||||||
.heapRange = {
|
.heapRange = {
|
||||||
.address = descriptorHeap->samplerHeap[currentBuffer].address,
|
.address = descriptorHeap->samplerHeap[i].address,
|
||||||
.size = static_cast<std::uint32_t>(descriptorHeap->samplerHeap[currentBuffer].size)
|
.size = static_cast<std::uint32_t>(descriptorHeap->samplerHeap[i].size)
|
||||||
},
|
},
|
||||||
.reservedRangeOffset = descriptorHeap->samplerHeap[currentBuffer].size - Device::descriptorHeapProperties.minSamplerHeapReservedRange,
|
.reservedRangeOffset = descriptorHeap->samplerHeap[i].size - Device::descriptorHeapProperties.minSamplerHeapReservedRange,
|
||||||
.reservedRangeSize = Device::descriptorHeapProperties.minSamplerHeapReservedRange
|
.reservedRangeSize = Device::descriptorHeapProperties.minSamplerHeapReservedRange
|
||||||
};
|
};
|
||||||
Device::vkCmdBindSamplerHeapEXT(drawCmdBuffers[currentBuffer], &samplerHeapInfo);
|
}
|
||||||
|
cachedDescriptorHeap = descriptorHeap;
|
||||||
|
}
|
||||||
|
Device::vkCmdBindResourceHeapEXT(drawCmdBuffers[currentBuffer], &resourceHeapInfos[currentBuffer]);
|
||||||
|
Device::vkCmdBindSamplerHeapEXT(drawCmdBuffers[currentBuffer], &samplerHeapInfos[currentBuffer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdate.Invoke({startTime, startTime-lastFrameBegin});
|
onUpdate.Invoke({startTime, startTime-lastFrameBegin});
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,18 @@ export namespace Crafter {
|
||||||
VkPipelineStageFlags submitPipelineStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
VkPipelineStageFlags submitPipelineStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
std::vector<RenderPass*> passes;
|
std::vector<RenderPass*> passes;
|
||||||
DescriptorHeapVulkan* descriptorHeap = nullptr;
|
DescriptorHeapVulkan* descriptorHeap = nullptr;
|
||||||
|
// Cached per-frame heap-bind structs. The heap address/size per slot
|
||||||
|
// are stable once a heap is assigned; only currentBuffer varies frame
|
||||||
|
// to frame, so the structs (and the reservedRangeOffset arithmetic)
|
||||||
|
// are computed once per heap rather than every frame in Render().
|
||||||
|
// Keyed on the heap pointer: whenever descriptorHeap differs from
|
||||||
|
// cachedDescriptorHeap the cache is rebuilt. This invalidates on any
|
||||||
|
// heap (re)assignment — heaps never resize today, so a stable pointer
|
||||||
|
// means stable ranges. Not tied to onResize (the heap is independent
|
||||||
|
// of swapchain size).
|
||||||
|
VkBindHeapInfoEXT resourceHeapInfos[numFrames];
|
||||||
|
VkBindHeapInfoEXT samplerHeapInfos[numFrames];
|
||||||
|
DescriptorHeapVulkan* cachedDescriptorHeap = nullptr;
|
||||||
std::optional<std::array<float, 4>> clearColor;
|
std::optional<std::array<float, 4>> clearColor;
|
||||||
#else
|
#else
|
||||||
// DOM mode: the page IS the window. WebGPU device and canvas are
|
// DOM mode: the page IS the window. WebGPU device and canvas are
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue