Merge pull request 'fix(device): preferred mask + required-only fallback for GetMemoryType (#59)' (#87) from claude/issue-59 into master

This commit is contained in:
catbot 2026-06-16 18:04:20 +02:00
commit c58b68ec40
6 changed files with 218 additions and 13 deletions

View file

@ -83,9 +83,14 @@ export namespace Crafter {
samplerFreelist.clear();
samplerFreelist.reserve(samplers);
// The heaps are written by the CPU every frame (HOST_VISIBLE is
// mandatory) and read by the GPU, so DEVICE_LOCAL is a perf
// preference, not a requirement: devices without a host-visible
// device-local heap (no resizable BAR) get a host-visible-only
// allocation instead of a hard allocation failure.
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
resourceHeap[i].Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, resourceSize);
samplerHeap[i].Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, samplerSize);
resourceHeap[i].Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, resourceSize, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
samplerHeap[i].Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_DESCRIPTOR_HEAP_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, samplerSize, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
}

View file

@ -199,7 +199,12 @@ export namespace Crafter {
// ComputeShader read the offset off the pipeline they record.
static void CheckVkResult(VkResult result);
static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags properties);
// Selects a memory type index from typeBits that satisfies `required`.
// When `preferred` bits are also given, a type satisfying both is
// chosen first; if none exists we fall back to required-only rather
// than throwing. Throws only when even `required` cannot be met (no
// valid memory exists for the allocation).
static std::uint32_t GetMemoryType(std::uint32_t typeBits, VkMemoryPropertyFlags required, VkMemoryPropertyFlags preferred = 0);
// ─── Wayland key repeat ────────────────────────────────────────
// TickKeyRepeats fires onRawKeyDown / onRawKeyHold / onTextInput on

View file

@ -55,7 +55,12 @@ namespace Crafter {
class VulkanBuffer : public VulkanBufferBase, public VulkanBufferMappedConditional<T, Mapped> {
public:
VulkanBuffer() = default;
void Create(VkBufferUsageFlags2 usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::uint32_t count) {
// `preferredPropertyFlags` are best-effort: the allocation prefers a
// memory type satisfying them on top of `memoryPropertyFlags`, but
// falls back to the required flags alone rather than failing. Use it
// for perf hints (e.g. DEVICE_LOCAL on a mapped buffer) that aren't
// available on every device — see Device::GetMemoryType.
void Create(VkBufferUsageFlags2 usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::uint32_t count, VkMemoryPropertyFlags preferredPropertyFlags = 0) {
size = count * sizeof(T);
// Carry usage in the maintenance5 flags2 chain so 64-bit bits
@ -77,7 +82,7 @@ namespace Crafter {
VkMemoryAllocateInfo memAlloc {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = memReqs.size,
.memoryTypeIndex = Device::GetMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags)
.memoryTypeIndex = Device::GetMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags, preferredPropertyFlags)
};
VkMemoryAllocateFlagsInfoKHR allocFlagsInfo {
@ -109,11 +114,11 @@ namespace Crafter {
buffer = VK_NULL_HANDLE;
}
void Resize(VkBufferUsageFlags2 usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::uint32_t count) {
void Resize(VkBufferUsageFlags2 usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::uint32_t count, VkMemoryPropertyFlags preferredPropertyFlags = 0) {
if(buffer != VK_NULL_HANDLE) {
Clear();
}
Create(usageFlags, memoryPropertyFlags, count);
Create(usageFlags, memoryPropertyFlags, count, preferredPropertyFlags);
}
void Copy(VkCommandBuffer cmd, VulkanBuffer& dst) {