Allocate one field's slots and register it.
64{
67 "VolumeGridBuffer: field declared with empty name, skipped");
68 return false;
69 }
70
71 if (stride_bytes == 0) {
73 "VolumeGridBuffer: field '{}' declares zero stride, skipped",
name);
74 return false;
75 }
76
79 "VolumeGridBuffer: duplicate field '{}', later declaration discarded",
name);
80 return false;
81 }
82
85
86 if (!buffer_service || !buffer_service->allocate_raw_buffer) {
87 error<std::runtime_error>(
90 std::source_location::current(),
91 "VolumeGridBuffer requires a valid buffer service");
92 }
93
94 const auto usage_flags = static_cast<uint32_t>(
95 static_cast<VkBufferUsageFlags>(
96 vk::BufferUsageFlagBits::eStorageBuffer
97 | vk::BufferUsageFlagBits::eTransferSrc
98 | vk::BufferUsageFlagBits::eTransferDst));
99
100 const auto memory_flags = static_cast<uint32_t>(
101 static_cast<VkMemoryPropertyFlags>(vk::MemoryPropertyFlagBits::eDeviceLocal));
102
104 const size_t field_bytes =
static_cast<size_t>(
get_cell_count()) * stride_bytes;
105 const uint32_t slot_count = double_buffered ? 2 : 1;
106
107 Field field {
108 .stride_bytes = stride_bytes,
109 .slot_a = static_cast<uint32_t>(resources.back_buffers.size()),
110 .slot_b = 0,
111 .read_is_a = true,
112 .semantics = semantics,
113 };
114
115 for (uint32_t i = 0; i < slot_count; ++i) {
116 void* out_buffer = nullptr;
117 void* out_memory = nullptr;
118 void* out_mapped = nullptr;
119
120 buffer_service->allocate_raw_buffer(
121 field_bytes, usage_flags, memory_flags, false,
122 out_buffer, out_memory, out_mapped);
123
124 VKBufferResources::GenerationSlot slot;
125 slot.buffer = static_cast<vk::Buffer>(static_cast<VkBuffer>(out_buffer));
126 slot.memory = static_cast<vk::DeviceMemory>(static_cast<VkDeviceMemory>(out_memory));
127 slot.mapped_ptr = out_mapped;
128
129 resources.back_buffers.push_back(slot);
130 }
131
132 field.slot_b = double_buffered ? field.slot_a + 1 : field.slot_a;
133
136
138 "VolumeGridBuffer: field '{}', stride {}, {} slot(s), {} bytes, class {}",
139 name, stride_bytes, slot_count, field_bytes * slot_count,
141
142 return true;
143}
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
const VKBufferResources & get_buffer_resources() const
Get all buffer resources at once (read-only)
std::unordered_map< std::string, Field > m_fields
uint32_t get_cell_count() const
Total cell count.
std::vector< std::string > m_field_order
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
constexpr std::string_view enum_to_string(EnumType value) noexcept
Universal enum to string converter using magic_enum (original case)