Merge remote-tracking branch 'origin/master' into claude/issue-73
# Conflicts: # interfaces/Crafter.Graphics-Mesh.cppm
This commit is contained in:
commit
aafa458d41
9 changed files with 473 additions and 14 deletions
|
|
@ -75,9 +75,12 @@ export namespace Crafter {
|
|||
VkImage image;
|
||||
VkDeviceMemory imageMemory;
|
||||
VulkanBuffer<PixelType, true> buffer;
|
||||
// Lives until the compressed Update path's cmd buffer completes.
|
||||
// Same lifetime contract as Mesh::compressedStaging — caller must
|
||||
// not destroy / re-Update before the submit fence is signaled.
|
||||
// Transient host-visible staging for the compressed Update path. Same
|
||||
// lifetime contract as Mesh::compressedStaging: the compressed Update
|
||||
// releases it via DeferredClear() right after recording the decompress,
|
||||
// so the fence-keyed deletion queue (#101/#102) frees it once that
|
||||
// submit's frame has cleared instead of pinning it for the image's life.
|
||||
// Between Updates the handle is null; the next Update's Resize re-creates it.
|
||||
VulkanBuffer<std::byte, true> compressedStaging;
|
||||
VkImageView imageView;
|
||||
VkDescriptorImageInfo descriptor;
|
||||
|
|
@ -299,6 +302,16 @@ export namespace Crafter {
|
|||
VK_PIPELINE_STAGE_2_COPY_BIT,
|
||||
VK_ACCESS_2_TRANSFER_READ_BIT);
|
||||
|
||||
// Compressed staging is read only by the decompress recorded above;
|
||||
// the buffer→image copy below reads `buffer` (the decompress dst),
|
||||
// never this. Release it to the fence-keyed deletion queue
|
||||
// (#101/#102) now instead of pinning host-visible memory for the
|
||||
// image's whole life. The recorded vkCmdDecompressMemoryEXT still
|
||||
// references compressedStaging.address, so it must outlive this
|
||||
// submit — which the queue guarantees by retiring the allocation
|
||||
// only after framesInFlight frames (i.e. after the submit's fence).
|
||||
compressedStaging.DeferredClear();
|
||||
|
||||
// Continue with the existing buffer→image upload + layout transitions.
|
||||
// We've already inserted the decompress→transfer-read barrier,
|
||||
// so we skip the FlushDevice host-write barrier the regular Update
|
||||
|
|
|
|||
|
|
@ -83,12 +83,13 @@ export namespace Crafter {
|
|||
// Lifetime contract matches vertexBuffer/indexBuffer: must stay
|
||||
// alive until the build submitted on `cmd` completes.
|
||||
VulkanBuffer<RTAabb, false> aabbBuffer;
|
||||
// Lives until the cmd buffer issued by the compressed Build path
|
||||
// completes execution. Kept as a member so the recorded
|
||||
// vkCmdDecompressMemoryEXT references valid memory until the queue
|
||||
// submit signals — caller must not re-Build or destroy the Mesh
|
||||
// before that submit's fence is signaled (same contract as the
|
||||
// existing uncompressed path).
|
||||
// Transient host-visible staging for the compressed Build path. Kept as
|
||||
// a member only so the recorded vkCmdDecompressMemoryEXT has a stable
|
||||
// address to reference; the compressed Build releases it via
|
||||
// DeferredClear() right after recording the decompress, so it is freed
|
||||
// by the fence-keyed deletion queue (#101/#102) once that submit's frame
|
||||
// has cleared — no longer pinned for the mesh's life. Between Builds the
|
||||
// handle is null; the next Build's Resize re-creates it.
|
||||
VulkanBuffer<std::byte, true> compressedStaging;
|
||||
VkAccelerationStructureGeometryTrianglesDataKHR blasData;
|
||||
VkAccelerationStructureGeometryKHR blas;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,30 @@ export namespace Crafter {
|
|||
hitRegion.size = hitGroups.size() * sbtStride;
|
||||
|
||||
std::size_t bufferSize = hitRegion.deviceAddress + hitRegion.size;
|
||||
sbtBuffer.Create(VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferSize);
|
||||
// The SBT is written once here (the memcpys below) and read by the
|
||||
// GPU on every vkCmdTraceRaysKHR for the pipeline's lifetime — the
|
||||
// textbook write-once/read-many buffer (issue #72). Get it into
|
||||
// device-local memory so trace dispatches read raygen/miss/hit
|
||||
// records out of VRAM instead of over PCIe from system RAM.
|
||||
//
|
||||
// Route the placement through #89: when a DEVICE_LOCAL|HOST_VISIBLE
|
||||
// type exists (ReBAR/UMA, or a BAR window — the SBT is tiny so the
|
||||
// window budget is never the constraint), prefer DEVICE_LOCAL on top
|
||||
// of the required HOST_VISIBLE so the allocation lands in device
|
||||
// memory we can still map. The one-time memcpy goes write-combined
|
||||
// over PCIe (write-only, sequential — ideal); GPU reads then hit
|
||||
// local VRAM. When no combined type exists at all (no spec
|
||||
// guarantee), PreferDirectDeviceWrite returns false and the preferred
|
||||
// hint is dropped, so GetMemoryType falls back to plain HOST_VISIBLE
|
||||
// (current behaviour, the per-trace PCIe read) — the cheaper fallback
|
||||
// the issue blesses while staging isn't wired here.
|
||||
//
|
||||
// Either way the buffer stays mapped, and the FlushDevice below gates
|
||||
// its flush on the *chosen* memory type's flags (issue #60), so a
|
||||
// direct-write type lacking HOST_COHERENT is still flushed correctly.
|
||||
VkMemoryPropertyFlags sbtPreferred = Device::PreferDirectDeviceWrite(bufferSize)
|
||||
? VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0;
|
||||
sbtBuffer.Create(VK_BUFFER_USAGE_2_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferSize, sbtPreferred);
|
||||
|
||||
std::uint8_t* offset = sbtBuffer.value;
|
||||
std::uint8_t* handleOffset = shaderHandles.data();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue